SGFreference Beta0.01
载入中...
搜索中...
未找到
json.hpp
浏览该文件的文档.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.3
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18/*
19MIT License
20
21Copyright (c) 2013-2022 Niels Lohmann
22
23Permission is hereby granted, free of charge, to any person obtaining a copy
24of this software and associated documentation files (the "Software"), to deal
25in the Software without restriction, including without limitation the rights
26to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27copies of the Software, and to permit persons to whom the Software is
28furnished to do so, subject to the following conditions:
29
30The above copyright notice and this permission notice shall be included in all
31copies or substantial portions of the Software.
32
33THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39SOFTWARE.
40*/
41
42#ifndef INCLUDE_NLOHMANN_JSON_HPP_
43#define INCLUDE_NLOHMANN_JSON_HPP_
44
45#include <algorithm> // all_of, find, for_each
46#include <cstddef> // nullptr_t, ptrdiff_t, size_t
47#include <functional> // hash, less
48#include <initializer_list> // initializer_list
49#ifndef JSON_NO_IO
50 #include <iosfwd> // istream, ostream
51#endif // JSON_NO_IO
52#include <iterator> // random_access_iterator_tag
53#include <memory> // unique_ptr
54#include <string> // string, stoi, to_string
55#include <utility> // declval, forward, move, pair, swap
56#include <vector> // vector
57
58// #include <nlohmann/adl_serializer.hpp>
59// __ _____ _____ _____
60// __| | __| | | | JSON for Modern C++
61// | | |__ | | | | | | version 3.11.3
62// |_____|_____|_____|_|___| https://github.com/nlohmann/json
63//
64// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
65// SPDX-License-Identifier: MIT
66
67
68
69#include <utility>
70
71// #include <nlohmann/detail/abi_macros.hpp>
72// __ _____ _____ _____
73// __| | __| | | | JSON for Modern C++
74// | | |__ | | | | | | version 3.11.3
75// |_____|_____|_____|_|___| https://github.com/nlohmann/json
76//
77// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
78// SPDX-License-Identifier: MIT
79
80
81
82// This file contains all macro definitions affecting or depending on the ABI
83
84#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
85 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
86 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
87 #warning "Already included a different version of the library!"
88 #endif
89 #endif
90#endif
91
92#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
93#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
94#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
95
96#ifndef JSON_DIAGNOSTICS
97 #define JSON_DIAGNOSTICS 0
98#endif
99
100#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
101 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
102#endif
103
104#if JSON_DIAGNOSTICS
105 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
106#else
107 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
108#endif
109
110#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
111 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
112#else
113 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
114#endif
115
116#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
117 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
118#endif
119
120// Construct the namespace ABI tags component
121#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
122#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
123 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
124
125#define NLOHMANN_JSON_ABI_TAGS \
126 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
127 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
128 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
129
130// Construct the namespace version component
131#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
132 _v ## major ## _ ## minor ## _ ## patch
133#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
134 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
135
136#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
137#define NLOHMANN_JSON_NAMESPACE_VERSION
138#else
139#define NLOHMANN_JSON_NAMESPACE_VERSION \
140 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
141 NLOHMANN_JSON_VERSION_MINOR, \
142 NLOHMANN_JSON_VERSION_PATCH)
143#endif
144
145// Combine namespace components
146#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
147#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
148 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
149
150#ifndef NLOHMANN_JSON_NAMESPACE
151#define NLOHMANN_JSON_NAMESPACE \
152 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
153 NLOHMANN_JSON_ABI_TAGS, \
154 NLOHMANN_JSON_NAMESPACE_VERSION)
155#endif
156
157#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
158#define NLOHMANN_JSON_NAMESPACE_BEGIN \
159 namespace nlohmann \
160 { \
161 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
162 NLOHMANN_JSON_ABI_TAGS, \
163 NLOHMANN_JSON_NAMESPACE_VERSION) \
164 {
165#endif
166
167#ifndef NLOHMANN_JSON_NAMESPACE_END
168#define NLOHMANN_JSON_NAMESPACE_END \
169 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
170 } // namespace nlohmann
171#endif
172
173// #include <nlohmann/detail/conversions/from_json.hpp>
174// __ _____ _____ _____
175// __| | __| | | | JSON for Modern C++
176// | | |__ | | | | | | version 3.11.3
177// |_____|_____|_____|_|___| https://github.com/nlohmann/json
178//
179// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
180// SPDX-License-Identifier: MIT
181
182
183
184#include <algorithm> // transform
185#include <array> // array
186#include <forward_list> // forward_list
187#include <iterator> // inserter, front_inserter, end
188#include <map> // map
189#include <string> // string
190#include <tuple> // tuple, make_tuple
191#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
192#include <unordered_map> // unordered_map
193#include <utility> // pair, declval
194#include <valarray> // valarray
195
196// #include <nlohmann/detail/exceptions.hpp>
197// __ _____ _____ _____
198// __| | __| | | | JSON for Modern C++
199// | | |__ | | | | | | version 3.11.3
200// |_____|_____|_____|_|___| https://github.com/nlohmann/json
201//
202// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
203// SPDX-License-Identifier: MIT
204
205
206
207#include <cstddef> // nullptr_t
208#include <exception> // exception
209#if JSON_DIAGNOSTICS
210 #include <numeric> // accumulate
211#endif
212#include <stdexcept> // runtime_error
213#include <string> // to_string
214#include <vector> // vector
215
216// #include <nlohmann/detail/value_t.hpp>
217// __ _____ _____ _____
218// __| | __| | | | JSON for Modern C++
219// | | |__ | | | | | | version 3.11.3
220// |_____|_____|_____|_|___| https://github.com/nlohmann/json
221//
222// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
223// SPDX-License-Identifier: MIT
224
225
226
227#include <array> // array
228#include <cstddef> // size_t
229#include <cstdint> // uint8_t
230#include <string> // string
231
232// #include <nlohmann/detail/macro_scope.hpp>
233// __ _____ _____ _____
234// __| | __| | | | JSON for Modern C++
235// | | |__ | | | | | | version 3.11.3
236// |_____|_____|_____|_|___| https://github.com/nlohmann/json
237//
238// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
239// SPDX-License-Identifier: MIT
240
241
242
243#include <utility> // declval, pair
244// #include <nlohmann/detail/meta/detected.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.11.3
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255#include <type_traits>
256
257// #include <nlohmann/detail/meta/void_t.hpp>
258// __ _____ _____ _____
259// __| | __| | | | JSON for Modern C++
260// | | |__ | | | | | | version 3.11.3
261// |_____|_____|_____|_|___| https://github.com/nlohmann/json
262//
263// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
264// SPDX-License-Identifier: MIT
265
266
267
268// #include <nlohmann/detail/abi_macros.hpp>
269
270
272namespace detail
273{
274
275template<typename ...Ts> struct make_void
276{
277 using type = void;
278};
279template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
280
281} // namespace detail
283
284
286namespace detail
287{
288
289// https://en.cppreference.com/w/cpp/experimental/is_detected
291{
292 nonesuch() = delete;
293 ~nonesuch() = delete;
294 nonesuch(nonesuch const&) = delete;
295 nonesuch(nonesuch const&&) = delete;
296 void operator=(nonesuch const&) = delete;
297 void operator=(nonesuch&&) = delete;
298};
299
300template<class Default,
301 class AlwaysVoid,
302 template<class...> class Op,
303 class... Args>
305{
306 using value_t = std::false_type;
307 using type = Default;
308};
309
310template<class Default, template<class...> class Op, class... Args>
311struct detector<Default, void_t<Op<Args...>>, Op, Args...>
312{
313 using value_t = std::true_type;
314 using type = Op<Args...>;
315};
316
317template<template<class...> class Op, class... Args>
318using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
319
320template<template<class...> class Op, class... Args>
321struct is_detected_lazy : is_detected<Op, Args...> { };
322
323template<template<class...> class Op, class... Args>
324using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
325
326template<class Default, template<class...> class Op, class... Args>
327using detected_or = detector<Default, void, Op, Args...>;
328
329template<class Default, template<class...> class Op, class... Args>
330using detected_or_t = typename detected_or<Default, Op, Args...>::type;
331
332template<class Expected, template<class...> class Op, class... Args>
333using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
334
335template<class To, template<class...> class Op, class... Args>
337 std::is_convertible<detected_t<Op, Args...>, To>;
338
339} // namespace detail
341
342// #include <nlohmann/thirdparty/hedley/hedley.hpp>
343
344
345// __ _____ _____ _____
346// __| | __| | | | JSON for Modern C++
347// | | |__ | | | | | | version 3.11.3
348// |_____|_____|_____|_|___| https://github.com/nlohmann/json
349//
350// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
351// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
352// SPDX-License-Identifier: MIT
353
354/* Hedley - https://nemequ.github.io/hedley
355 * Created by Evan Nemerson <evan@nemerson.com>
356 */
357
358#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
359#if defined(JSON_HEDLEY_VERSION)
360 #undef JSON_HEDLEY_VERSION
361#endif
362#define JSON_HEDLEY_VERSION 15
363
364#if defined(JSON_HEDLEY_STRINGIFY_EX)
365 #undef JSON_HEDLEY_STRINGIFY_EX
366#endif
367#define JSON_HEDLEY_STRINGIFY_EX(x) #x
368
369#if defined(JSON_HEDLEY_STRINGIFY)
370 #undef JSON_HEDLEY_STRINGIFY
371#endif
372#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
373
374#if defined(JSON_HEDLEY_CONCAT_EX)
375 #undef JSON_HEDLEY_CONCAT_EX
376#endif
377#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
378
379#if defined(JSON_HEDLEY_CONCAT)
380 #undef JSON_HEDLEY_CONCAT
381#endif
382#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
383
384#if defined(JSON_HEDLEY_CONCAT3_EX)
385 #undef JSON_HEDLEY_CONCAT3_EX
386#endif
387#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
388
389#if defined(JSON_HEDLEY_CONCAT3)
390 #undef JSON_HEDLEY_CONCAT3
391#endif
392#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
393
394#if defined(JSON_HEDLEY_VERSION_ENCODE)
395 #undef JSON_HEDLEY_VERSION_ENCODE
396#endif
397#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
398
399#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
400 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
401#endif
402#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
403
404#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
405 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
406#endif
407#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
408
409#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
410 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
411#endif
412#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
413
414#if defined(JSON_HEDLEY_GNUC_VERSION)
415 #undef JSON_HEDLEY_GNUC_VERSION
416#endif
417#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
418 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
419#elif defined(__GNUC__)
420 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
421#endif
422
423#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
424 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
425#endif
426#if defined(JSON_HEDLEY_GNUC_VERSION)
427 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
428#else
429 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
430#endif
431
432#if defined(JSON_HEDLEY_MSVC_VERSION)
433 #undef JSON_HEDLEY_MSVC_VERSION
434#endif
435#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
436 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
437#elif defined(_MSC_FULL_VER) && !defined(__ICL)
438 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
439#elif defined(_MSC_VER) && !defined(__ICL)
440 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
441#endif
442
443#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
444 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
445#endif
446#if !defined(JSON_HEDLEY_MSVC_VERSION)
447 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
448#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
449 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
450#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
451 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
452#else
453 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
454#endif
455
456#if defined(JSON_HEDLEY_INTEL_VERSION)
457 #undef JSON_HEDLEY_INTEL_VERSION
458#endif
459#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
460 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
461#elif defined(__INTEL_COMPILER) && !defined(__ICL)
462 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
463#endif
464
465#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
466 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
467#endif
468#if defined(JSON_HEDLEY_INTEL_VERSION)
469 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
470#else
471 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
472#endif
473
474#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
475 #undef JSON_HEDLEY_INTEL_CL_VERSION
476#endif
477#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
478 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
479#endif
480
481#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
482 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
483#endif
484#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
485 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
486#else
487 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
488#endif
489
490#if defined(JSON_HEDLEY_PGI_VERSION)
491 #undef JSON_HEDLEY_PGI_VERSION
492#endif
493#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
494 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
495#endif
496
497#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
498 #undef JSON_HEDLEY_PGI_VERSION_CHECK
499#endif
500#if defined(JSON_HEDLEY_PGI_VERSION)
501 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
502#else
503 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
504#endif
505
506#if defined(JSON_HEDLEY_SUNPRO_VERSION)
507 #undef JSON_HEDLEY_SUNPRO_VERSION
508#endif
509#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
510 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
511#elif defined(__SUNPRO_C)
512 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
513#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
514 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
515#elif defined(__SUNPRO_CC)
516 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
517#endif
518
519#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
520 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
521#endif
522#if defined(JSON_HEDLEY_SUNPRO_VERSION)
523 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
524#else
525 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
526#endif
527
528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
529 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
530#endif
531#if defined(__EMSCRIPTEN__)
532 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
533#endif
534
535#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
536 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
537#endif
538#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
539 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
540#else
541 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
542#endif
543
544#if defined(JSON_HEDLEY_ARM_VERSION)
545 #undef JSON_HEDLEY_ARM_VERSION
546#endif
547#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
548 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
549#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
550 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
551#endif
552
553#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
554 #undef JSON_HEDLEY_ARM_VERSION_CHECK
555#endif
556#if defined(JSON_HEDLEY_ARM_VERSION)
557 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
558#else
559 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
560#endif
561
562#if defined(JSON_HEDLEY_IBM_VERSION)
563 #undef JSON_HEDLEY_IBM_VERSION
564#endif
565#if defined(__ibmxl__)
566 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
567#elif defined(__xlC__) && defined(__xlC_ver__)
568 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
569#elif defined(__xlC__)
570 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
571#endif
572
573#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
574 #undef JSON_HEDLEY_IBM_VERSION_CHECK
575#endif
576#if defined(JSON_HEDLEY_IBM_VERSION)
577 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578#else
579 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
580#endif
581
582#if defined(JSON_HEDLEY_TI_VERSION)
583 #undef JSON_HEDLEY_TI_VERSION
584#endif
585#if \
586 defined(__TI_COMPILER_VERSION__) && \
587 ( \
588 defined(__TMS470__) || defined(__TI_ARM__) || \
589 defined(__MSP430__) || \
590 defined(__TMS320C2000__) \
591 )
592#if (__TI_COMPILER_VERSION__ >= 16000000)
593 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
594#endif
595#endif
596
597#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
598 #undef JSON_HEDLEY_TI_VERSION_CHECK
599#endif
600#if defined(JSON_HEDLEY_TI_VERSION)
601 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
602#else
603 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
604#endif
605
606#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
607 #undef JSON_HEDLEY_TI_CL2000_VERSION
608#endif
609#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
610 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
611#endif
612
613#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
614 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
615#endif
616#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
617 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
618#else
619 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
620#endif
621
622#if defined(JSON_HEDLEY_TI_CL430_VERSION)
623 #undef JSON_HEDLEY_TI_CL430_VERSION
624#endif
625#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
626 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
627#endif
628
629#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
630 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
631#endif
632#if defined(JSON_HEDLEY_TI_CL430_VERSION)
633 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
634#else
635 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
636#endif
637
638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
639 #undef JSON_HEDLEY_TI_ARMCL_VERSION
640#endif
641#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
642 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
643#endif
644
645#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
646 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
647#endif
648#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
649 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
650#else
651 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
652#endif
653
654#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
655 #undef JSON_HEDLEY_TI_CL6X_VERSION
656#endif
657#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
658 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
659#endif
660
661#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
662 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
663#endif
664#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
665 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
666#else
667 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
668#endif
669
670#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
671 #undef JSON_HEDLEY_TI_CL7X_VERSION
672#endif
673#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
674 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
675#endif
676
677#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
678 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
679#endif
680#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
681 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
682#else
683 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
684#endif
685
686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
687 #undef JSON_HEDLEY_TI_CLPRU_VERSION
688#endif
689#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
690 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
691#endif
692
693#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
694 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
695#endif
696#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
697 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698#else
699 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
700#endif
701
702#if defined(JSON_HEDLEY_CRAY_VERSION)
703 #undef JSON_HEDLEY_CRAY_VERSION
704#endif
705#if defined(_CRAYC)
706 #if defined(_RELEASE_PATCHLEVEL)
707 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
708 #else
709 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
710 #endif
711#endif
712
713#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
714 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
715#endif
716#if defined(JSON_HEDLEY_CRAY_VERSION)
717 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
718#else
719 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
720#endif
721
722#if defined(JSON_HEDLEY_IAR_VERSION)
723 #undef JSON_HEDLEY_IAR_VERSION
724#endif
725#if defined(__IAR_SYSTEMS_ICC__)
726 #if __VER__ > 1000
727 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
728 #else
729 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
730 #endif
731#endif
732
733#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
734 #undef JSON_HEDLEY_IAR_VERSION_CHECK
735#endif
736#if defined(JSON_HEDLEY_IAR_VERSION)
737 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
738#else
739 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
740#endif
741
742#if defined(JSON_HEDLEY_TINYC_VERSION)
743 #undef JSON_HEDLEY_TINYC_VERSION
744#endif
745#if defined(__TINYC__)
746 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
747#endif
748
749#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
750 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
751#endif
752#if defined(JSON_HEDLEY_TINYC_VERSION)
753 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
754#else
755 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
756#endif
757
758#if defined(JSON_HEDLEY_DMC_VERSION)
759 #undef JSON_HEDLEY_DMC_VERSION
760#endif
761#if defined(__DMC__)
762 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
763#endif
764
765#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
766 #undef JSON_HEDLEY_DMC_VERSION_CHECK
767#endif
768#if defined(JSON_HEDLEY_DMC_VERSION)
769 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
770#else
771 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
772#endif
773
774#if defined(JSON_HEDLEY_COMPCERT_VERSION)
775 #undef JSON_HEDLEY_COMPCERT_VERSION
776#endif
777#if defined(__COMPCERT_VERSION__)
778 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
779#endif
780
781#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
782 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
783#endif
784#if defined(JSON_HEDLEY_COMPCERT_VERSION)
785 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
786#else
787 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
788#endif
789
790#if defined(JSON_HEDLEY_PELLES_VERSION)
791 #undef JSON_HEDLEY_PELLES_VERSION
792#endif
793#if defined(__POCC__)
794 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
795#endif
796
797#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
798 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
799#endif
800#if defined(JSON_HEDLEY_PELLES_VERSION)
801 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
802#else
803 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
804#endif
805
806#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
807 #undef JSON_HEDLEY_MCST_LCC_VERSION
808#endif
809#if defined(__LCC__) && defined(__LCC_MINOR__)
810 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
811#endif
812
813#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
814 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
815#endif
816#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
817 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
818#else
819 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
820#endif
821
822#if defined(JSON_HEDLEY_GCC_VERSION)
823 #undef JSON_HEDLEY_GCC_VERSION
824#endif
825#if \
826 defined(JSON_HEDLEY_GNUC_VERSION) && \
827 !defined(__clang__) && \
828 !defined(JSON_HEDLEY_INTEL_VERSION) && \
829 !defined(JSON_HEDLEY_PGI_VERSION) && \
830 !defined(JSON_HEDLEY_ARM_VERSION) && \
831 !defined(JSON_HEDLEY_CRAY_VERSION) && \
832 !defined(JSON_HEDLEY_TI_VERSION) && \
833 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
834 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
835 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
836 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
837 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
838 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
839 !defined(__COMPCERT__) && \
840 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
841 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
842#endif
843
844#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
845 #undef JSON_HEDLEY_GCC_VERSION_CHECK
846#endif
847#if defined(JSON_HEDLEY_GCC_VERSION)
848 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
849#else
850 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
851#endif
852
853#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
854 #undef JSON_HEDLEY_HAS_ATTRIBUTE
855#endif
856#if \
857 defined(__has_attribute) && \
858 ( \
859 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
860 )
861# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
862#else
863# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
864#endif
865
866#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
867 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
868#endif
869#if defined(__has_attribute)
870 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
871#else
872 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
873#endif
874
875#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
876 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
877#endif
878#if defined(__has_attribute)
879 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
880#else
881 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
882#endif
883
884#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
885 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
886#endif
887#if \
888 defined(__has_cpp_attribute) && \
889 defined(__cplusplus) && \
890 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
891 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
892#else
893 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
894#endif
895
896#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
897 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
898#endif
899#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
900 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
901#elif \
902 !defined(JSON_HEDLEY_PGI_VERSION) && \
903 !defined(JSON_HEDLEY_IAR_VERSION) && \
904 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
905 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
906 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
907#else
908 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
909#endif
910
911#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
912 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
913#endif
914#if defined(__has_cpp_attribute) && defined(__cplusplus)
915 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
916#else
917 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
918#endif
919
920#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
921 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
922#endif
923#if defined(__has_cpp_attribute) && defined(__cplusplus)
924 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
925#else
926 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
927#endif
928
929#if defined(JSON_HEDLEY_HAS_BUILTIN)
930 #undef JSON_HEDLEY_HAS_BUILTIN
931#endif
932#if defined(__has_builtin)
933 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
934#else
935 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
936#endif
937
938#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
939 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
940#endif
941#if defined(__has_builtin)
942 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
943#else
944 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
945#endif
946
947#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
948 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
949#endif
950#if defined(__has_builtin)
951 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
952#else
953 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
954#endif
955
956#if defined(JSON_HEDLEY_HAS_FEATURE)
957 #undef JSON_HEDLEY_HAS_FEATURE
958#endif
959#if defined(__has_feature)
960 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
961#else
962 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
963#endif
964
965#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
966 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
967#endif
968#if defined(__has_feature)
969 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
970#else
971 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
972#endif
973
974#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
975 #undef JSON_HEDLEY_GCC_HAS_FEATURE
976#endif
977#if defined(__has_feature)
978 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
979#else
980 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
981#endif
982
983#if defined(JSON_HEDLEY_HAS_EXTENSION)
984 #undef JSON_HEDLEY_HAS_EXTENSION
985#endif
986#if defined(__has_extension)
987 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
988#else
989 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
990#endif
991
992#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
993 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
994#endif
995#if defined(__has_extension)
996 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
997#else
998 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
999#endif
1000
1001#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
1002 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
1003#endif
1004#if defined(__has_extension)
1005 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
1006#else
1007 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1008#endif
1009
1010#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1011 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1012#endif
1013#if defined(__has_declspec_attribute)
1014 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1015#else
1016 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1017#endif
1018
1019#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1020 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1021#endif
1022#if defined(__has_declspec_attribute)
1023 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1024#else
1025 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1026#endif
1027
1028#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1029 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1030#endif
1031#if defined(__has_declspec_attribute)
1032 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1033#else
1034 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1035#endif
1036
1037#if defined(JSON_HEDLEY_HAS_WARNING)
1038 #undef JSON_HEDLEY_HAS_WARNING
1039#endif
1040#if defined(__has_warning)
1041 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1042#else
1043 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1044#endif
1045
1046#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1047 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1048#endif
1049#if defined(__has_warning)
1050 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1051#else
1052 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1053#endif
1054
1055#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1056 #undef JSON_HEDLEY_GCC_HAS_WARNING
1057#endif
1058#if defined(__has_warning)
1059 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1060#else
1061 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1062#endif
1063
1064#if \
1065 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1066 defined(__clang__) || \
1067 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1068 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1069 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1070 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1071 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1072 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1073 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1074 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1075 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1076 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1077 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1078 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1079 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1080 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1081 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1082 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1083 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1084#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1085 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1086#else
1087 #define JSON_HEDLEY_PRAGMA(value)
1088#endif
1089
1090#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1091 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1092#endif
1093#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1094 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1095#endif
1096#if defined(__clang__)
1097 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1098 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1099#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1101 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1102#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1103 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1104 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1105#elif \
1106 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1107 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1108 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1109 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1110#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1111 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1112 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1113#elif \
1114 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1115 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1116 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1117 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1118 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1119 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1120 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1121 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1122#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1123 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1124 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1125#else
1126 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1127 #define JSON_HEDLEY_DIAGNOSTIC_POP
1128#endif
1129
1130/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1131 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1132#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1133 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1134#endif
1135#if defined(__cplusplus)
1136# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1137# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1138# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1139# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1140 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1141 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1142 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1143 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1144 xpr \
1145 JSON_HEDLEY_DIAGNOSTIC_POP
1146# else
1147# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1148 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1149 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1150 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1151 xpr \
1152 JSON_HEDLEY_DIAGNOSTIC_POP
1153# endif
1154# else
1155# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1156 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1157 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1158 xpr \
1159 JSON_HEDLEY_DIAGNOSTIC_POP
1160# endif
1161# endif
1162#endif
1163#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1164 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1165#endif
1166
1167#if defined(JSON_HEDLEY_CONST_CAST)
1168 #undef JSON_HEDLEY_CONST_CAST
1169#endif
1170#if defined(__cplusplus)
1171# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1172#elif \
1173 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1174 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1175 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1176# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1177 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1178 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1179 ((T) (expr)); \
1180 JSON_HEDLEY_DIAGNOSTIC_POP \
1181 }))
1182#else
1183# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1184#endif
1185
1186#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1187 #undef JSON_HEDLEY_REINTERPRET_CAST
1188#endif
1189#if defined(__cplusplus)
1190 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1191#else
1192 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1193#endif
1194
1195#if defined(JSON_HEDLEY_STATIC_CAST)
1196 #undef JSON_HEDLEY_STATIC_CAST
1197#endif
1198#if defined(__cplusplus)
1199 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1200#else
1201 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1202#endif
1203
1204#if defined(JSON_HEDLEY_CPP_CAST)
1205 #undef JSON_HEDLEY_CPP_CAST
1206#endif
1207#if defined(__cplusplus)
1208# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1209# define JSON_HEDLEY_CPP_CAST(T, expr) \
1210 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1211 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1212 ((T) (expr)) \
1213 JSON_HEDLEY_DIAGNOSTIC_POP
1214# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1215# define JSON_HEDLEY_CPP_CAST(T, expr) \
1216 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1217 _Pragma("diag_suppress=Pe137") \
1218 JSON_HEDLEY_DIAGNOSTIC_POP
1219# else
1220# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1221# endif
1222#else
1223# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1224#endif
1225
1226#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1227 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1228#endif
1229#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1231#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1233#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1235#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1236 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1237#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1238 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1239#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1240 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1241#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1242 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1243#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1244 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1245#elif \
1246 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1247 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1248 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1249 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1250 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1251 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1252 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1253 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1254 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1255 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1256 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1257 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1258#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1259 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1260#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1261 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1262#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1264#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1266#else
1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1268#endif
1269
1270#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1271 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1272#endif
1273#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1275#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1276 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1277#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1279#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1281#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1283#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1285#elif \
1286 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1287 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1288 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1289 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1290 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1291#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1292 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1293#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1295#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1297#else
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1299#endif
1300
1301#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1302 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1303#endif
1304#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1306#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1308#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1310#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1312#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1314#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1316#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1318#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1320#elif \
1321 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1322 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1323 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1324 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1325#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1327#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1329#else
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1331#endif
1332
1333#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1334 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1335#endif
1336#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1337 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1338#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1339 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1340#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1342#else
1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1344#endif
1345
1346#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1347 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1348#endif
1349#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1350 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1351#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1352 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1353#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1354 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1355#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1356 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1357#else
1358 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1359#endif
1360
1361#if defined(JSON_HEDLEY_DEPRECATED)
1362 #undef JSON_HEDLEY_DEPRECATED
1363#endif
1364#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1365 #undef JSON_HEDLEY_DEPRECATED_FOR
1366#endif
1367#if \
1368 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1369 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1370 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1371 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1372#elif \
1373 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1374 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1375 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1376 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1377 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1378 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1379 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1380 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1381 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1382 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1383 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1384 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1385 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1386 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1387#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1388 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1389 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1390#elif \
1391 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1392 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1393 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1394 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1395 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1396 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1397 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1398 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1399 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1400 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1401 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1402 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1403 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1404 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1405 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1406 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1407 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1408 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1409#elif \
1410 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1411 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1412 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1413 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1414 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1415#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1416 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1417 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1418#else
1419 #define JSON_HEDLEY_DEPRECATED(since)
1420 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1421#endif
1422
1423#if defined(JSON_HEDLEY_UNAVAILABLE)
1424 #undef JSON_HEDLEY_UNAVAILABLE
1425#endif
1426#if \
1427 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1428 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1429 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1430 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1431 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1432#else
1433 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1434#endif
1435
1436#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1437 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1438#endif
1439#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1440 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1441#endif
1442#if \
1443 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1444 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1445 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1446 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1447 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1448 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1449 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1450 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1451 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1452 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1453 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1454 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1455 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1456 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1457 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1458 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1459 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1461 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1462#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1463 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1464 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1465#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1466 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1467 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1468#elif defined(_Check_return_) /* SAL */
1469 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1470 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1471#else
1472 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1473 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1474#endif
1475
1476#if defined(JSON_HEDLEY_SENTINEL)
1477 #undef JSON_HEDLEY_SENTINEL
1478#endif
1479#if \
1480 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1481 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1482 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1483 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1484 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1485 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1486#else
1487 #define JSON_HEDLEY_SENTINEL(position)
1488#endif
1489
1490#if defined(JSON_HEDLEY_NO_RETURN)
1491 #undef JSON_HEDLEY_NO_RETURN
1492#endif
1493#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1494 #define JSON_HEDLEY_NO_RETURN __noreturn
1495#elif \
1496 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1497 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1498 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1499#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1500 #define JSON_HEDLEY_NO_RETURN _Noreturn
1501#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1502 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1503#elif \
1504 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1505 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1506 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1507 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1508 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1509 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1510 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1511 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1512 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1513 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1514 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1515 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1516 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1517 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1518 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1519 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1520 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1521 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1522#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1523 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1524#elif \
1525 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1526 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1527 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1528#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1529 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1530#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1531 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1532#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1533 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1534#else
1535 #define JSON_HEDLEY_NO_RETURN
1536#endif
1537
1538#if defined(JSON_HEDLEY_NO_ESCAPE)
1539 #undef JSON_HEDLEY_NO_ESCAPE
1540#endif
1541#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1542 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1543#else
1544 #define JSON_HEDLEY_NO_ESCAPE
1545#endif
1546
1547#if defined(JSON_HEDLEY_UNREACHABLE)
1548 #undef JSON_HEDLEY_UNREACHABLE
1549#endif
1550#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1551 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1552#endif
1553#if defined(JSON_HEDLEY_ASSUME)
1554 #undef JSON_HEDLEY_ASSUME
1555#endif
1556#if \
1557 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1558 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1559 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1560 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1561#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1562 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1563#elif \
1564 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1565 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1566 #if defined(__cplusplus)
1567 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1568 #else
1569 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1570 #endif
1571#endif
1572#if \
1573 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1574 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1575 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1576 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1577 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1578 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1579 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1580 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1581#elif defined(JSON_HEDLEY_ASSUME)
1582 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1583#endif
1584#if !defined(JSON_HEDLEY_ASSUME)
1585 #if defined(JSON_HEDLEY_UNREACHABLE)
1586 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1587 #else
1588 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1589 #endif
1590#endif
1591#if defined(JSON_HEDLEY_UNREACHABLE)
1592 #if \
1593 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1594 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1595 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1596 #else
1597 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1598 #endif
1599#else
1600 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1601#endif
1602#if !defined(JSON_HEDLEY_UNREACHABLE)
1603 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1604#endif
1605
1607#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1608 #pragma clang diagnostic ignored "-Wpedantic"
1609#endif
1610#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1611 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1612#endif
1613#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1614 #if defined(__clang__)
1615 #pragma clang diagnostic ignored "-Wvariadic-macros"
1616 #elif defined(JSON_HEDLEY_GCC_VERSION)
1617 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1618 #endif
1619#endif
1620#if defined(JSON_HEDLEY_NON_NULL)
1621 #undef JSON_HEDLEY_NON_NULL
1622#endif
1623#if \
1624 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1625 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1626 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1627 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1628 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1629#else
1630 #define JSON_HEDLEY_NON_NULL(...)
1631#endif
1633
1634#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1635 #undef JSON_HEDLEY_PRINTF_FORMAT
1636#endif
1637#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1638 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1639#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1640 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1641#elif \
1642 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1643 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1644 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1645 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1646 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1647 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1648 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1649 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1650 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1651 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1652 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1653 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1654 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1655 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1656 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1657 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1658 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1659 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1660#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1661 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1662#else
1663 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1664#endif
1665
1666#if defined(JSON_HEDLEY_CONSTEXPR)
1667 #undef JSON_HEDLEY_CONSTEXPR
1668#endif
1669#if defined(__cplusplus)
1670 #if __cplusplus >= 201103L
1671 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1672 #endif
1673#endif
1674#if !defined(JSON_HEDLEY_CONSTEXPR)
1675 #define JSON_HEDLEY_CONSTEXPR
1676#endif
1677
1678#if defined(JSON_HEDLEY_PREDICT)
1679 #undef JSON_HEDLEY_PREDICT
1680#endif
1681#if defined(JSON_HEDLEY_LIKELY)
1682 #undef JSON_HEDLEY_LIKELY
1683#endif
1684#if defined(JSON_HEDLEY_UNLIKELY)
1685 #undef JSON_HEDLEY_UNLIKELY
1686#endif
1687#if defined(JSON_HEDLEY_UNPREDICTABLE)
1688 #undef JSON_HEDLEY_UNPREDICTABLE
1689#endif
1690#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1691 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1692#endif
1693#if \
1694 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1695 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1696 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1697# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1698# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1699# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1700# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1701# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1702#elif \
1703 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1704 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1705 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1706 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1707 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1708 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1709 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1710 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1711 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1712 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1713 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1714 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1715 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1716 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1717 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1718 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1719# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1720 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1721# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1722 (__extension__ ({ \
1723 double hedley_probability_ = (probability); \
1724 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1725 }))
1726# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1727 (__extension__ ({ \
1728 double hedley_probability_ = (probability); \
1729 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1730 }))
1731# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1732# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1733#else
1734# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1735# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1736# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1737# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1738# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1739#endif
1740#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1741 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1742#endif
1743
1744#if defined(JSON_HEDLEY_MALLOC)
1745 #undef JSON_HEDLEY_MALLOC
1746#endif
1747#if \
1748 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1749 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1750 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1751 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1752 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1753 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1754 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1755 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1756 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1757 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1758 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1759 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1760 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1761 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1762 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1763 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1764 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1765 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1766 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1767#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1768 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1769#elif \
1770 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1771 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1772 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1773#else
1774 #define JSON_HEDLEY_MALLOC
1775#endif
1776
1777#if defined(JSON_HEDLEY_PURE)
1778 #undef JSON_HEDLEY_PURE
1779#endif
1780#if \
1781 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1782 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1783 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1784 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1785 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1786 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1787 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1788 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1789 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1790 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1791 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1792 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1793 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1794 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1795 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1796 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1797 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1798 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1799 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1800# define JSON_HEDLEY_PURE __attribute__((__pure__))
1801#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1802# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1803#elif defined(__cplusplus) && \
1804 ( \
1805 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1806 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1807 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1808 )
1809# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1810#else
1811# define JSON_HEDLEY_PURE
1812#endif
1813
1814#if defined(JSON_HEDLEY_CONST)
1815 #undef JSON_HEDLEY_CONST
1816#endif
1817#if \
1818 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1819 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1820 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1821 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1822 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1823 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1824 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1825 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1826 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1827 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1828 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1829 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1830 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1831 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1832 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1833 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1834 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1835 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1836 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1837 #define JSON_HEDLEY_CONST __attribute__((__const__))
1838#elif \
1839 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1840 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1841#else
1842 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1843#endif
1844
1845#if defined(JSON_HEDLEY_RESTRICT)
1846 #undef JSON_HEDLEY_RESTRICT
1847#endif
1848#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1849 #define JSON_HEDLEY_RESTRICT restrict
1850#elif \
1851 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1852 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1853 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1854 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1855 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1856 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1857 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1858 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1859 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1860 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1861 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1862 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1863 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1864 defined(__clang__) || \
1865 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1866 #define JSON_HEDLEY_RESTRICT __restrict
1867#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1868 #define JSON_HEDLEY_RESTRICT _Restrict
1869#else
1870 #define JSON_HEDLEY_RESTRICT
1871#endif
1872
1873#if defined(JSON_HEDLEY_INLINE)
1874 #undef JSON_HEDLEY_INLINE
1875#endif
1876#if \
1877 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1878 (defined(__cplusplus) && (__cplusplus >= 199711L))
1879 #define JSON_HEDLEY_INLINE inline
1880#elif \
1881 defined(JSON_HEDLEY_GCC_VERSION) || \
1882 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1883 #define JSON_HEDLEY_INLINE __inline__
1884#elif \
1885 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1886 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1887 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1889 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1891 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1892 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1893 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1894 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1895 #define JSON_HEDLEY_INLINE __inline
1896#else
1897 #define JSON_HEDLEY_INLINE
1898#endif
1899
1900#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1901 #undef JSON_HEDLEY_ALWAYS_INLINE
1902#endif
1903#if \
1904 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1905 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1906 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1907 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1908 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1909 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1910 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1911 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1912 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1913 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1914 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1915 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1916 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1917 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1918 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1919 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1920 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1921 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1922 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1923# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1924#elif \
1925 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1926 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1927# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1928#elif defined(__cplusplus) && \
1929 ( \
1930 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1931 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1932 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1933 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1934 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1935 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1936 )
1937# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1938#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1939# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1940#else
1941# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1942#endif
1943
1944#if defined(JSON_HEDLEY_NEVER_INLINE)
1945 #undef JSON_HEDLEY_NEVER_INLINE
1946#endif
1947#if \
1948 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1949 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1950 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1951 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1952 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1953 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1954 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1955 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1956 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1957 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1958 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1959 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1960 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1961 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1962 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1963 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1964 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1965 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1966 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1967 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1968#elif \
1969 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1970 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1971 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1972#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1973 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1974#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1975 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1976#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1977 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1978#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1979 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1980#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1981 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1982#else
1983 #define JSON_HEDLEY_NEVER_INLINE
1984#endif
1985
1986#if defined(JSON_HEDLEY_PRIVATE)
1987 #undef JSON_HEDLEY_PRIVATE
1988#endif
1989#if defined(JSON_HEDLEY_PUBLIC)
1990 #undef JSON_HEDLEY_PUBLIC
1991#endif
1992#if defined(JSON_HEDLEY_IMPORT)
1993 #undef JSON_HEDLEY_IMPORT
1994#endif
1995#if defined(_WIN32) || defined(__CYGWIN__)
1996# define JSON_HEDLEY_PRIVATE
1997# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1998# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1999#else
2000# if \
2001 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
2002 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2003 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
2004 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2005 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2006 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2007 ( \
2008 defined(__TI_EABI__) && \
2009 ( \
2010 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2011 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2012 ) \
2013 ) || \
2014 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2015# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2016# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2017# else
2018# define JSON_HEDLEY_PRIVATE
2019# define JSON_HEDLEY_PUBLIC
2020# endif
2021# define JSON_HEDLEY_IMPORT extern
2022#endif
2023
2024#if defined(JSON_HEDLEY_NO_THROW)
2025 #undef JSON_HEDLEY_NO_THROW
2026#endif
2027#if \
2028 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2029 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2030 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2031 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2032 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2033#elif \
2034 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2035 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2036 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2037 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2038#else
2039 #define JSON_HEDLEY_NO_THROW
2040#endif
2041
2042#if defined(JSON_HEDLEY_FALL_THROUGH)
2043 #undef JSON_HEDLEY_FALL_THROUGH
2044#endif
2045#if \
2046 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2047 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2048 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2049 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2050#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2051 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2052#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2053 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2054#elif defined(__fallthrough) /* SAL */
2055 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2056#else
2057 #define JSON_HEDLEY_FALL_THROUGH
2058#endif
2059
2060#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2061 #undef JSON_HEDLEY_RETURNS_NON_NULL
2062#endif
2063#if \
2064 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2065 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2066 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2067 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2068#elif defined(_Ret_notnull_) /* SAL */
2069 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2070#else
2071 #define JSON_HEDLEY_RETURNS_NON_NULL
2072#endif
2073
2074#if defined(JSON_HEDLEY_ARRAY_PARAM)
2075 #undef JSON_HEDLEY_ARRAY_PARAM
2076#endif
2077#if \
2078 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2079 !defined(__STDC_NO_VLA__) && \
2080 !defined(__cplusplus) && \
2081 !defined(JSON_HEDLEY_PGI_VERSION) && \
2082 !defined(JSON_HEDLEY_TINYC_VERSION)
2083 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2084#else
2085 #define JSON_HEDLEY_ARRAY_PARAM(name)
2086#endif
2087
2088#if defined(JSON_HEDLEY_IS_CONSTANT)
2089 #undef JSON_HEDLEY_IS_CONSTANT
2090#endif
2091#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2092 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2093#endif
2094/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2095 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2096#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2097 #undef JSON_HEDLEY_IS_CONSTEXPR_
2098#endif
2099#if \
2100 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2101 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2102 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2103 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2104 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2105 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2106 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2107 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2108 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2109 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2110 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2111#endif
2112#if !defined(__cplusplus)
2113# if \
2114 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2115 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2116 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2117 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2118 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2119 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2120 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2121#if defined(__INTPTR_TYPE__)
2122 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2123#else
2124 #include <stdint.h>
2125 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2126#endif
2127# elif \
2128 ( \
2129 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2130 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2131 !defined(JSON_HEDLEY_PGI_VERSION) && \
2132 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2133 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2134 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2135 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2136 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2137 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2138#if defined(__INTPTR_TYPE__)
2139 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2140#else
2141 #include <stdint.h>
2142 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2143#endif
2144# elif \
2145 defined(JSON_HEDLEY_GCC_VERSION) || \
2146 defined(JSON_HEDLEY_INTEL_VERSION) || \
2147 defined(JSON_HEDLEY_TINYC_VERSION) || \
2148 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2149 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2150 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2151 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2152 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2153 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2154 defined(__clang__)
2155# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2156 sizeof(void) != \
2157 sizeof(*( \
2158 1 ? \
2159 ((void*) ((expr) * 0L) ) : \
2160((struct { char v[sizeof(void) * 2]; } *) 1) \
2161 ) \
2162 ) \
2163 )
2164# endif
2165#endif
2166#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2167 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2168 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2169 #endif
2170 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2171#else
2172 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2173 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2174 #endif
2175 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2176#endif
2177
2178#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2179 #undef JSON_HEDLEY_BEGIN_C_DECLS
2180#endif
2181#if defined(JSON_HEDLEY_END_C_DECLS)
2182 #undef JSON_HEDLEY_END_C_DECLS
2183#endif
2184#if defined(JSON_HEDLEY_C_DECL)
2185 #undef JSON_HEDLEY_C_DECL
2186#endif
2187#if defined(__cplusplus)
2188 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2189 #define JSON_HEDLEY_END_C_DECLS }
2190 #define JSON_HEDLEY_C_DECL extern "C"
2191#else
2192 #define JSON_HEDLEY_BEGIN_C_DECLS
2193 #define JSON_HEDLEY_END_C_DECLS
2194 #define JSON_HEDLEY_C_DECL
2195#endif
2196
2197#if defined(JSON_HEDLEY_STATIC_ASSERT)
2198 #undef JSON_HEDLEY_STATIC_ASSERT
2199#endif
2200#if \
2201 !defined(__cplusplus) && ( \
2202 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2203 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2204 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2205 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2206 defined(_Static_assert) \
2207 )
2208# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2209#elif \
2210 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2211 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2212 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2213# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2214#else
2215# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2216#endif
2217
2218#if defined(JSON_HEDLEY_NULL)
2219 #undef JSON_HEDLEY_NULL
2220#endif
2221#if defined(__cplusplus)
2222 #if __cplusplus >= 201103L
2223 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2224 #elif defined(NULL)
2225 #define JSON_HEDLEY_NULL NULL
2226 #else
2227 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2228 #endif
2229#elif defined(NULL)
2230 #define JSON_HEDLEY_NULL NULL
2231#else
2232 #define JSON_HEDLEY_NULL ((void*) 0)
2233#endif
2234
2235#if defined(JSON_HEDLEY_MESSAGE)
2236 #undef JSON_HEDLEY_MESSAGE
2237#endif
2238#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2239# define JSON_HEDLEY_MESSAGE(msg) \
2240 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2241 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2242 JSON_HEDLEY_PRAGMA(message msg) \
2243 JSON_HEDLEY_DIAGNOSTIC_POP
2244#elif \
2245 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2247# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2248#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2249# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2250#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2251# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2252#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2253# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2254#else
2255# define JSON_HEDLEY_MESSAGE(msg)
2256#endif
2257
2258#if defined(JSON_HEDLEY_WARNING)
2259 #undef JSON_HEDLEY_WARNING
2260#endif
2261#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2262# define JSON_HEDLEY_WARNING(msg) \
2263 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2264 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2265 JSON_HEDLEY_PRAGMA(clang warning msg) \
2266 JSON_HEDLEY_DIAGNOSTIC_POP
2267#elif \
2268 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2269 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2270 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2271# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2272#elif \
2273 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2274 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2275# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2276#else
2277# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2278#endif
2279
2280#if defined(JSON_HEDLEY_REQUIRE)
2281 #undef JSON_HEDLEY_REQUIRE
2282#endif
2283#if defined(JSON_HEDLEY_REQUIRE_MSG)
2284 #undef JSON_HEDLEY_REQUIRE_MSG
2285#endif
2286#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2287# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2288# define JSON_HEDLEY_REQUIRE(expr) \
2289 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2290 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2291 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2292 JSON_HEDLEY_DIAGNOSTIC_POP
2293# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2294 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2295 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2296 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2297 JSON_HEDLEY_DIAGNOSTIC_POP
2298# else
2299# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2300# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2301# endif
2302#else
2303# define JSON_HEDLEY_REQUIRE(expr)
2304# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2305#endif
2306
2307#if defined(JSON_HEDLEY_FLAGS)
2308 #undef JSON_HEDLEY_FLAGS
2309#endif
2310#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2311 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2312#else
2313 #define JSON_HEDLEY_FLAGS
2314#endif
2315
2316#if defined(JSON_HEDLEY_FLAGS_CAST)
2317 #undef JSON_HEDLEY_FLAGS_CAST
2318#endif
2319#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2320# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2321 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2322 _Pragma("warning(disable:188)") \
2323 ((T) (expr)); \
2324 JSON_HEDLEY_DIAGNOSTIC_POP \
2325 }))
2326#else
2327# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2328#endif
2329
2330#if defined(JSON_HEDLEY_EMPTY_BASES)
2331 #undef JSON_HEDLEY_EMPTY_BASES
2332#endif
2333#if \
2334 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2335 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2336 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2337#else
2338 #define JSON_HEDLEY_EMPTY_BASES
2339#endif
2340
2341/* Remaining macros are deprecated. */
2342
2343#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2344 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2345#endif
2346#if defined(__clang__)
2347 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2348#else
2349 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2350#endif
2351
2352#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2353 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2356
2357#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2358 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2361
2362#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2363 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2366
2367#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2368 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2369#endif
2370#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2371
2372#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2373 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2374#endif
2375#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2376
2377#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2378 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2379#endif
2380#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2381
2382#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2383 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2384#endif
2385#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2386
2387#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2388
2389
2390// This file contains all internal macro definitions (except those affecting ABI)
2391// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2392
2393// #include <nlohmann/detail/abi_macros.hpp>
2394
2395
2396// exclude unsupported compilers
2397#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2398 #if defined(__clang__)
2399 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2401 #endif
2402 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2403 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2404 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2405 #endif
2406 #endif
2407#endif
2408
2409// C++ language standard detection
2410// if the user manually specified the used c++ version this is skipped
2411#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2412 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2413 #define JSON_HAS_CPP_20
2414 #define JSON_HAS_CPP_17
2415 #define JSON_HAS_CPP_14
2416 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2417 #define JSON_HAS_CPP_17
2418 #define JSON_HAS_CPP_14
2419 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2420 #define JSON_HAS_CPP_14
2421 #endif
2422 // the cpp 11 flag is always specified because it is the minimal required version
2423 #define JSON_HAS_CPP_11
2424#endif
2425
2426#ifdef __has_include
2427 #if __has_include(<version>)
2428 #include <version>
2429 #endif
2430#endif
2431
2432#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2433 #ifdef JSON_HAS_CPP_17
2434 #if defined(__cpp_lib_filesystem)
2435 #define JSON_HAS_FILESYSTEM 1
2436 #elif defined(__cpp_lib_experimental_filesystem)
2437 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2438 #elif !defined(__has_include)
2439 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2440 #elif __has_include(<filesystem>)
2441 #define JSON_HAS_FILESYSTEM 1
2442 #elif __has_include(<experimental/filesystem>)
2443 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2444 #endif
2445
2446 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2447 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2448 #undef JSON_HAS_FILESYSTEM
2449 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2450 #endif
2451
2452 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2453 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2454 #undef JSON_HAS_FILESYSTEM
2455 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2456 #endif
2457
2458 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2459 #if defined(__clang_major__) && __clang_major__ < 7
2460 #undef JSON_HAS_FILESYSTEM
2461 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2462 #endif
2463
2464 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2465 #if defined(_MSC_VER) && _MSC_VER < 1914
2466 #undef JSON_HAS_FILESYSTEM
2467 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2468 #endif
2469
2470 // no filesystem support before iOS 13
2471 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2472 #undef JSON_HAS_FILESYSTEM
2473 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2474 #endif
2475
2476 // no filesystem support before macOS Catalina
2477 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2478 #undef JSON_HAS_FILESYSTEM
2479 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2480 #endif
2481 #endif
2482#endif
2483
2484#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2485 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2486#endif
2487
2488#ifndef JSON_HAS_FILESYSTEM
2489 #define JSON_HAS_FILESYSTEM 0
2490#endif
2491
2492#ifndef JSON_HAS_THREE_WAY_COMPARISON
2493 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2494 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2495 #define JSON_HAS_THREE_WAY_COMPARISON 1
2496 #else
2497 #define JSON_HAS_THREE_WAY_COMPARISON 0
2498 #endif
2499#endif
2500
2501#ifndef JSON_HAS_RANGES
2502 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2503 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2504 #define JSON_HAS_RANGES 0
2505 #elif defined(__cpp_lib_ranges)
2506 #define JSON_HAS_RANGES 1
2507 #else
2508 #define JSON_HAS_RANGES 0
2509 #endif
2510#endif
2511
2512#ifndef JSON_HAS_STATIC_RTTI
2513 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2514 #define JSON_HAS_STATIC_RTTI 1
2515 #else
2516 #define JSON_HAS_STATIC_RTTI 0
2517 #endif
2518#endif
2519
2520#ifdef JSON_HAS_CPP_17
2521 #define JSON_INLINE_VARIABLE inline
2522#else
2523 #define JSON_INLINE_VARIABLE
2524#endif
2525
2526#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2527 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2528#else
2529 #define JSON_NO_UNIQUE_ADDRESS
2530#endif
2531
2532// disable documentation warnings on clang
2533#if defined(__clang__)
2534 #pragma clang diagnostic push
2535 #pragma clang diagnostic ignored "-Wdocumentation"
2536 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2537#endif
2538
2539// allow disabling exceptions
2540#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2541 #define JSON_THROW(exception) throw exception
2542 #define JSON_TRY try
2543 #define JSON_CATCH(exception) catch(exception)
2544 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2545#else
2546 #include <cstdlib>
2547 #define JSON_THROW(exception) std::abort()
2548 #define JSON_TRY if(true)
2549 #define JSON_CATCH(exception) if(false)
2550 #define JSON_INTERNAL_CATCH(exception) if(false)
2551#endif
2552
2553// override exception macros
2554#if defined(JSON_THROW_USER)
2555 #undef JSON_THROW
2556 #define JSON_THROW JSON_THROW_USER
2557#endif
2558#if defined(JSON_TRY_USER)
2559 #undef JSON_TRY
2560 #define JSON_TRY JSON_TRY_USER
2561#endif
2562#if defined(JSON_CATCH_USER)
2563 #undef JSON_CATCH
2564 #define JSON_CATCH JSON_CATCH_USER
2565 #undef JSON_INTERNAL_CATCH
2566 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2567#endif
2568#if defined(JSON_INTERNAL_CATCH_USER)
2569 #undef JSON_INTERNAL_CATCH
2570 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2571#endif
2572
2573// allow overriding assert
2574#if !defined(JSON_ASSERT)
2575 #include <cassert> // assert
2576 #define JSON_ASSERT(x) assert(x)
2577#endif
2578
2579// allow to access some private functions (needed by the test suite)
2580#if defined(JSON_TESTS_PRIVATE)
2581 #define JSON_PRIVATE_UNLESS_TESTED public
2582#else
2583 #define JSON_PRIVATE_UNLESS_TESTED private
2584#endif
2585
2591#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2592 template<typename BasicJsonType> \
2593 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2594 { \
2595 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2596 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2597 auto it = std::find_if(std::begin(m), std::end(m), \
2598 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2599 { \
2600 return ej_pair.first == e; \
2601 }); \
2602 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2603 } \
2604 template<typename BasicJsonType> \
2605 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2606 { \
2607 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2608 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2609 auto it = std::find_if(std::begin(m), std::end(m), \
2610 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2611 { \
2612 return ej_pair.second == j; \
2613 }); \
2614 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2615 }
2616
2617// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2618// may be removed in the future once the class is split.
2619
2620#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2621 template<template<typename, typename, typename...> class ObjectType, \
2622 template<typename, typename...> class ArrayType, \
2623 class StringType, class BooleanType, class NumberIntegerType, \
2624 class NumberUnsignedType, class NumberFloatType, \
2625 template<typename> class AllocatorType, \
2626 template<typename, typename = void> class JSONSerializer, \
2627 class BinaryType, \
2628 class CustomBaseClass>
2629
2630#define NLOHMANN_BASIC_JSON_TPL \
2631 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2632 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2633 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2634
2635// Macros to simplify conversion from/to types
2636
2637#define NLOHMANN_JSON_EXPAND( x ) x
2638#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2639#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2640 NLOHMANN_JSON_PASTE64, \
2641 NLOHMANN_JSON_PASTE63, \
2642 NLOHMANN_JSON_PASTE62, \
2643 NLOHMANN_JSON_PASTE61, \
2644 NLOHMANN_JSON_PASTE60, \
2645 NLOHMANN_JSON_PASTE59, \
2646 NLOHMANN_JSON_PASTE58, \
2647 NLOHMANN_JSON_PASTE57, \
2648 NLOHMANN_JSON_PASTE56, \
2649 NLOHMANN_JSON_PASTE55, \
2650 NLOHMANN_JSON_PASTE54, \
2651 NLOHMANN_JSON_PASTE53, \
2652 NLOHMANN_JSON_PASTE52, \
2653 NLOHMANN_JSON_PASTE51, \
2654 NLOHMANN_JSON_PASTE50, \
2655 NLOHMANN_JSON_PASTE49, \
2656 NLOHMANN_JSON_PASTE48, \
2657 NLOHMANN_JSON_PASTE47, \
2658 NLOHMANN_JSON_PASTE46, \
2659 NLOHMANN_JSON_PASTE45, \
2660 NLOHMANN_JSON_PASTE44, \
2661 NLOHMANN_JSON_PASTE43, \
2662 NLOHMANN_JSON_PASTE42, \
2663 NLOHMANN_JSON_PASTE41, \
2664 NLOHMANN_JSON_PASTE40, \
2665 NLOHMANN_JSON_PASTE39, \
2666 NLOHMANN_JSON_PASTE38, \
2667 NLOHMANN_JSON_PASTE37, \
2668 NLOHMANN_JSON_PASTE36, \
2669 NLOHMANN_JSON_PASTE35, \
2670 NLOHMANN_JSON_PASTE34, \
2671 NLOHMANN_JSON_PASTE33, \
2672 NLOHMANN_JSON_PASTE32, \
2673 NLOHMANN_JSON_PASTE31, \
2674 NLOHMANN_JSON_PASTE30, \
2675 NLOHMANN_JSON_PASTE29, \
2676 NLOHMANN_JSON_PASTE28, \
2677 NLOHMANN_JSON_PASTE27, \
2678 NLOHMANN_JSON_PASTE26, \
2679 NLOHMANN_JSON_PASTE25, \
2680 NLOHMANN_JSON_PASTE24, \
2681 NLOHMANN_JSON_PASTE23, \
2682 NLOHMANN_JSON_PASTE22, \
2683 NLOHMANN_JSON_PASTE21, \
2684 NLOHMANN_JSON_PASTE20, \
2685 NLOHMANN_JSON_PASTE19, \
2686 NLOHMANN_JSON_PASTE18, \
2687 NLOHMANN_JSON_PASTE17, \
2688 NLOHMANN_JSON_PASTE16, \
2689 NLOHMANN_JSON_PASTE15, \
2690 NLOHMANN_JSON_PASTE14, \
2691 NLOHMANN_JSON_PASTE13, \
2692 NLOHMANN_JSON_PASTE12, \
2693 NLOHMANN_JSON_PASTE11, \
2694 NLOHMANN_JSON_PASTE10, \
2695 NLOHMANN_JSON_PASTE9, \
2696 NLOHMANN_JSON_PASTE8, \
2697 NLOHMANN_JSON_PASTE7, \
2698 NLOHMANN_JSON_PASTE6, \
2699 NLOHMANN_JSON_PASTE5, \
2700 NLOHMANN_JSON_PASTE4, \
2701 NLOHMANN_JSON_PASTE3, \
2702 NLOHMANN_JSON_PASTE2, \
2703 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2704#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2705#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2706#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2707#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2708#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2709#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2710#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2711#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2712#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2713#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2714#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2715#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2716#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2717#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2718#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2719#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2720#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2721#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2722#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2723#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2724#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2725#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2726#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2727#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2728#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2729#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2730#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2731#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2732#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2733#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2734#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2735#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2736#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2737#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2738#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2739#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2740#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2741#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2742#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2743#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2744#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2745#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2746#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2747#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2748#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2749#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2750#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2751#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2752#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2753#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2754#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2755#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2756#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2757#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2758#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2759#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2760#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2761#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2762#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2763#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2764#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2765#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2766#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2767
2768#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2769#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2770#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2771
2777#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2778 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2779 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780
2781#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2782 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2783 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2784
2785#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2786 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2787
2793#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2794 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2795 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2796
2797#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2798 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2799
2800#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2801 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2802 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2803
2804// inspired from https://stackoverflow.com/a/26745591
2805// allows to call any std function as if (e.g. with begin):
2806// using std::begin; begin(x);
2807//
2808// it allows using the detected idiom to retrieve the return type
2809// of such an expression
2810#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2811 namespace detail { \
2812 using std::std_name; \
2813 \
2814 template<typename... T> \
2815 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2816 } \
2817 \
2818 namespace detail2 { \
2819 struct std_name##_tag \
2820 { \
2821 }; \
2822 \
2823 template<typename... T> \
2824 std_name##_tag std_name(T&&...); \
2825 \
2826 template<typename... T> \
2827 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2828 \
2829 template<typename... T> \
2830 struct would_call_std_##std_name \
2831 { \
2832 static constexpr auto const value = ::nlohmann::detail:: \
2833 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2834 }; \
2835 } /* namespace detail2 */ \
2836 \
2837 template<typename... T> \
2838 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2839 { \
2840 }
2841
2842#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2843 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2844#endif
2845
2846#if JSON_USE_IMPLICIT_CONVERSIONS
2847 #define JSON_EXPLICIT
2848#else
2849 #define JSON_EXPLICIT explicit
2850#endif
2851
2852#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2853 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2854#endif
2855
2856#ifndef JSON_USE_GLOBAL_UDLS
2857 #define JSON_USE_GLOBAL_UDLS 1
2858#endif
2859
2860#if JSON_HAS_THREE_WAY_COMPARISON
2861 #include <compare> // partial_ordering
2862#endif
2863
2865namespace detail
2866{
2867
2869// JSON type enumeration //
2871
2896enum class value_t : std::uint8_t
2897{
2898 null,
2899 object,
2900 array,
2901 string,
2902 boolean,
2905 number_float,
2906 binary,
2907 discarded
2908};
2909
2923#if JSON_HAS_THREE_WAY_COMPARISON
2924 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2925#else
2926 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2927#endif
2928{
2929 static constexpr std::array<std::uint8_t, 9> order = {{
2930 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2931 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2932 6 /* binary */
2933 }
2934 };
2935
2936 const auto l_index = static_cast<std::size_t>(lhs);
2937 const auto r_index = static_cast<std::size_t>(rhs);
2938#if JSON_HAS_THREE_WAY_COMPARISON
2939 if (l_index < order.size() && r_index < order.size())
2940 {
2941 return order[l_index] <=> order[r_index]; // *NOPAD*
2942 }
2943 return std::partial_ordering::unordered;
2944#else
2945 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2946#endif
2947}
2948
2949// GCC selects the built-in operator< over an operator rewritten from
2950// a user-defined spaceship operator
2951// Clang, MSVC, and ICC select the rewritten candidate
2952// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2953#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2954inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2955{
2956 return std::is_lt(lhs <=> rhs); // *NOPAD*
2957}
2958#endif
2959
2960} // namespace detail
2962
2963// #include <nlohmann/detail/string_escape.hpp>
2964// __ _____ _____ _____
2965// __| | __| | | | JSON for Modern C++
2966// | | |__ | | | | | | version 3.11.3
2967// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2968//
2969// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2970// SPDX-License-Identifier: MIT
2971
2972
2973
2974// #include <nlohmann/detail/abi_macros.hpp>
2975
2976
2978namespace detail
2979{
2980
2994template<typename StringType>
2995inline void replace_substring(StringType& s, const StringType& f,
2996 const StringType& t)
2997{
2998 JSON_ASSERT(!f.empty());
2999 for (auto pos = s.find(f); // find first occurrence of f
3000 pos != StringType::npos; // make sure f was found
3001 s.replace(pos, f.size(), t), // replace with t, and
3002 pos = s.find(f, pos + t.size())) // find next occurrence of f
3003 {}
3004}
3005
3013template<typename StringType>
3014inline StringType escape(StringType s)
3015{
3016 replace_substring(s, StringType{"~"}, StringType{"~0"});
3017 replace_substring(s, StringType{"/"}, StringType{"~1"});
3018 return s;
3019}
3020
3028template<typename StringType>
3029static void unescape(StringType& s)
3030{
3031 replace_substring(s, StringType{"~1"}, StringType{"/"});
3032 replace_substring(s, StringType{"~0"}, StringType{"~"});
3033}
3034
3035} // namespace detail
3037
3038// #include <nlohmann/detail/input/position_t.hpp>
3039// __ _____ _____ _____
3040// __| | __| | | | JSON for Modern C++
3041// | | |__ | | | | | | version 3.11.3
3042// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3043//
3044// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3045// SPDX-License-Identifier: MIT
3046
3047
3048
3049#include <cstddef> // size_t
3050
3051// #include <nlohmann/detail/abi_macros.hpp>
3052
3053
3055namespace detail
3056{
3057
3060{
3062 std::size_t chars_read_total = 0;
3066 std::size_t lines_read = 0;
3067
3069 constexpr operator size_t() const
3070 {
3071 return chars_read_total;
3072 }
3073};
3074
3075} // namespace detail
3077
3078// #include <nlohmann/detail/macro_scope.hpp>
3079
3080// #include <nlohmann/detail/meta/cpp_future.hpp>
3081// __ _____ _____ _____
3082// __| | __| | | | JSON for Modern C++
3083// | | |__ | | | | | | version 3.11.3
3084// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3085//
3086// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3087// SPDX-FileCopyrightText: 2018 The Abseil Authors
3088// SPDX-License-Identifier: MIT
3089
3090
3091
3092#include <array> // array
3093#include <cstddef> // size_t
3094#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3095#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3096
3097// #include <nlohmann/detail/macro_scope.hpp>
3098
3099
3101namespace detail
3102{
3103
3104template<typename T>
3105using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3106
3107#ifdef JSON_HAS_CPP_14
3108
3109// the following utilities are natively available in C++14
3110using std::enable_if_t;
3111using std::index_sequence;
3112using std::make_index_sequence;
3113using std::index_sequence_for;
3114
3115#else
3116
3117// alias templates to reduce boilerplate
3118template<bool B, typename T = void>
3119using enable_if_t = typename std::enable_if<B, T>::type;
3120
3121// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3122// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3123
3125
3126// integer_sequence
3127//
3128// Class template representing a compile-time integer sequence. An instantiation
3129// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3130// type through its template arguments (which is a common need when
3131// working with C++11 variadic templates). `absl::integer_sequence` is designed
3132// to be a drop-in replacement for C++14's `std::integer_sequence`.
3133//
3134// Example:
3135//
3136// template< class T, T... Ints >
3137// void user_function(integer_sequence<T, Ints...>);
3138//
3139// int main()
3140// {
3141// // user_function's `T` will be deduced to `int` and `Ints...`
3142// // will be deduced to `0, 1, 2, 3, 4`.
3143// user_function(make_integer_sequence<int, 5>());
3144// }
3145template <typename T, T... Ints>
3147{
3148 using value_type = T;
3149 static constexpr std::size_t size() noexcept
3150 {
3151 return sizeof...(Ints);
3152 }
3153};
3154
3155// index_sequence
3156//
3157// A helper template for an `integer_sequence` of `size_t`,
3158// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3159// `std::index_sequence`.
3160template <size_t... Ints>
3161using index_sequence = integer_sequence<size_t, Ints...>;
3162
3163namespace utility_internal
3164{
3165
3166template <typename Seq, size_t SeqSize, size_t Rem>
3167struct Extend;
3168
3169// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3170template <typename T, T... Ints, size_t SeqSize>
3171struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3172{
3173 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3174};
3175
3176template <typename T, T... Ints, size_t SeqSize>
3177struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3178{
3179 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3180};
3181
3182// Recursion helper for 'make_integer_sequence<T, N>'.
3183// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3184template <typename T, size_t N>
3185struct Gen
3186{
3187 using type =
3188 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3189};
3190
3191template <typename T>
3192struct Gen<T, 0>
3193{
3195};
3196
3197} // namespace utility_internal
3198
3199// Compile-time sequences of integers
3200
3201// make_integer_sequence
3202//
3203// This template alias is equivalent to
3204// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3205// replacement for C++14's `std::make_integer_sequence`.
3206template <typename T, T N>
3208
3209// make_index_sequence
3210//
3211// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3212// and is designed to be a drop-in replacement for C++14's
3213// `std::make_index_sequence`.
3214template <size_t N>
3216
3217// index_sequence_for
3218//
3219// Converts a typename pack into an index sequence of the same length, and
3220// is designed to be a drop-in replacement for C++14's
3221// `std::index_sequence_for()`
3222template <typename... Ts>
3224
3226
3227#endif
3228
3229// dispatch utility (taken from ranges-v3)
3230template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3231template<> struct priority_tag<0> {};
3232
3233// taken from ranges-v3
3234template<typename T>
3236{
3237 static JSON_INLINE_VARIABLE constexpr T value{};
3238};
3239
3240#ifndef JSON_HAS_CPP_17
3241 template<typename T>
3242 constexpr T static_const<T>::value;
3243#endif
3244
3245template<typename T, typename... Args>
3246inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3247{
3248 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3249}
3250
3251} // namespace detail
3253
3254// #include <nlohmann/detail/meta/type_traits.hpp>
3255// __ _____ _____ _____
3256// __| | __| | | | JSON for Modern C++
3257// | | |__ | | | | | | version 3.11.3
3258// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3259//
3260// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3261// SPDX-License-Identifier: MIT
3262
3263
3264
3265#include <limits> // numeric_limits
3266#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3267#include <utility> // declval
3268#include <tuple> // tuple
3269#include <string> // char_traits
3270
3271// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3272// __ _____ _____ _____
3273// __| | __| | | | JSON for Modern C++
3274// | | |__ | | | | | | version 3.11.3
3275// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3276//
3277// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3278// SPDX-License-Identifier: MIT
3279
3280
3281
3282#include <iterator> // random_access_iterator_tag
3283
3284// #include <nlohmann/detail/abi_macros.hpp>
3285
3286// #include <nlohmann/detail/meta/void_t.hpp>
3287
3288// #include <nlohmann/detail/meta/cpp_future.hpp>
3289
3290
3292namespace detail
3293{
3294
3295template<typename It, typename = void>
3297
3298template<typename It>
3300 It,
3301 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3302 typename It::reference, typename It::iterator_category >>
3303{
3304 using difference_type = typename It::difference_type;
3305 using value_type = typename It::value_type;
3306 using pointer = typename It::pointer;
3307 using reference = typename It::reference;
3308 using iterator_category = typename It::iterator_category;
3309};
3310
3311// This is required as some compilers implement std::iterator_traits in a way that
3312// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3313template<typename T, typename = void>
3315{
3316};
3317
3318template<typename T>
3319struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3320 : iterator_types<T>
3321{
3322};
3323
3324template<typename T>
3326{
3327 using iterator_category = std::random_access_iterator_tag;
3328 using value_type = T;
3329 using difference_type = ptrdiff_t;
3330 using pointer = T*;
3331 using reference = T&;
3332};
3333
3334} // namespace detail
3336
3337// #include <nlohmann/detail/macro_scope.hpp>
3338
3339// #include <nlohmann/detail/meta/call_std/begin.hpp>
3340// __ _____ _____ _____
3341// __| | __| | | | JSON for Modern C++
3342// | | |__ | | | | | | version 3.11.3
3343// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3344//
3345// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3346// SPDX-License-Identifier: MIT
3347
3348
3349
3350// #include <nlohmann/detail/macro_scope.hpp>
3351
3352
3354
3356
3358
3359// #include <nlohmann/detail/meta/call_std/end.hpp>
3360// __ _____ _____ _____
3361// __| | __| | | | JSON for Modern C++
3362// | | |__ | | | | | | version 3.11.3
3363// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3364//
3365// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3366// SPDX-License-Identifier: MIT
3367
3368
3369
3370// #include <nlohmann/detail/macro_scope.hpp>
3371
3372
3374
3376
3378
3379// #include <nlohmann/detail/meta/cpp_future.hpp>
3380
3381// #include <nlohmann/detail/meta/detected.hpp>
3382
3383// #include <nlohmann/json_fwd.hpp>
3384// __ _____ _____ _____
3385// __| | __| | | | JSON for Modern C++
3386// | | |__ | | | | | | version 3.11.3
3387// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3388//
3389// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3390// SPDX-License-Identifier: MIT
3391
3392#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3393 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3394
3395 #include <cstdint> // int64_t, uint64_t
3396 #include <map> // map
3397 #include <memory> // allocator
3398 #include <string> // string
3399 #include <vector> // vector
3400
3401 // #include <nlohmann/detail/abi_macros.hpp>
3402
3403
3410
3418 template<typename T = void, typename SFINAE = void>
3419 struct adl_serializer;
3420
3423 template<template<typename U, typename V, typename... Args> class ObjectType =
3424 std::map,
3425 template<typename U, typename... Args> class ArrayType = std::vector,
3426 class StringType = std::string, class BooleanType = bool,
3427 class NumberIntegerType = std::int64_t,
3428 class NumberUnsignedType = std::uint64_t,
3429 class NumberFloatType = double,
3430 template<typename U> class AllocatorType = std::allocator,
3431 template<typename T, typename SFINAE = void> class JSONSerializer =
3433 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3434 class CustomBaseClass = void>
3435 class basic_json;
3436
3439 template<typename RefStringType>
3440 class json_pointer;
3441
3447
3450 template<class Key, class T, class IgnoredLess, class Allocator>
3451 struct ordered_map;
3452
3456
3458
3459#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3460
3461
3471namespace detail
3472{
3473
3475// helpers //
3477
3478// Note to maintainers:
3479//
3480// Every trait in this file expects a non CV-qualified type.
3481// The only exceptions are in the 'aliases for detected' section
3482// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3483//
3484// In this case, T has to be properly CV-qualified to constraint the function arguments
3485// (e.g. to_json(BasicJsonType&, const T&))
3486
3487template<typename> struct is_basic_json : std::false_type {};
3488
3490struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3491
3492// used by exceptions create() member functions
3493// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3494// false_type otherwise
3495template<typename BasicJsonContext>
3497 std::integral_constant < bool,
3498 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3499 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3500{};
3501
3503// json_ref helpers //
3505
3506template<typename>
3507class json_ref;
3508
3509template<typename>
3510struct is_json_ref : std::false_type {};
3511
3512template<typename T>
3513struct is_json_ref<json_ref<T>> : std::true_type {};
3514
3516// aliases for detected //
3518
3519template<typename T>
3520using mapped_type_t = typename T::mapped_type;
3521
3522template<typename T>
3523using key_type_t = typename T::key_type;
3524
3525template<typename T>
3526using value_type_t = typename T::value_type;
3527
3528template<typename T>
3529using difference_type_t = typename T::difference_type;
3530
3531template<typename T>
3532using pointer_t = typename T::pointer;
3533
3534template<typename T>
3535using reference_t = typename T::reference;
3536
3537template<typename T>
3538using iterator_category_t = typename T::iterator_category;
3539
3540template<typename T, typename... Args>
3541using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3542
3543template<typename T, typename... Args>
3544using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3545
3546template<typename T, typename U>
3547using get_template_function = decltype(std::declval<T>().template get<U>());
3548
3549// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3550template<typename BasicJsonType, typename T, typename = void>
3551struct has_from_json : std::false_type {};
3552
3553// trait checking if j.get<T> is valid
3554// use this trait instead of std::is_constructible or std::is_convertible,
3555// both rely on, or make use of implicit conversions, and thus fail when T
3556// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3557template <typename BasicJsonType, typename T>
3562
3563template<typename BasicJsonType, typename T>
3564struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3565{
3566 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3567
3568 static constexpr bool value =
3570 const BasicJsonType&, T&>::value;
3571};
3572
3573// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3574// this overload is used for non-default-constructible user-defined-types
3575template<typename BasicJsonType, typename T, typename = void>
3576struct has_non_default_from_json : std::false_type {};
3577
3578template<typename BasicJsonType, typename T>
3579struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3580{
3581 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3582
3583 static constexpr bool value =
3585 const BasicJsonType&>::value;
3586};
3587
3588// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3589// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3590template<typename BasicJsonType, typename T, typename = void>
3591struct has_to_json : std::false_type {};
3592
3593template<typename BasicJsonType, typename T>
3594struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3595{
3596 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3597
3598 static constexpr bool value =
3599 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3600 T>::value;
3601};
3602
3603template<typename T>
3604using detect_key_compare = typename T::key_compare;
3605
3606template<typename T>
3607struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3608
3609// obtains the actual object key comparator
3610template<typename BasicJsonType>
3612{
3613 using object_t = typename BasicJsonType::object_t;
3614 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3615 using type = typename std::conditional < has_key_compare<object_t>::value,
3616 typename object_t::key_compare, object_comparator_t>::type;
3617};
3618
3619template<typename BasicJsonType>
3621
3623// char_traits //
3625
3626// Primary template of char_traits calls std char_traits
3627template<typename T>
3628struct char_traits : std::char_traits<T>
3629{};
3630
3631// Explicitly define char traits for unsigned char since it is not standard
3632template<>
3633struct char_traits<unsigned char> : std::char_traits<char>
3634{
3635 using char_type = unsigned char;
3636 using int_type = uint64_t;
3637
3638 // Redefine to_int_type function
3639 static int_type to_int_type(char_type c) noexcept
3640 {
3641 return static_cast<int_type>(c);
3642 }
3643
3645 {
3646 return static_cast<char_type>(i);
3647 }
3648
3649 static constexpr int_type eof() noexcept
3650 {
3651 return static_cast<int_type>(EOF);
3652 }
3653};
3654
3655// Explicitly define char traits for signed char since it is not standard
3656template<>
3657struct char_traits<signed char> : std::char_traits<char>
3658{
3659 using char_type = signed char;
3660 using int_type = uint64_t;
3661
3662 // Redefine to_int_type function
3663 static int_type to_int_type(char_type c) noexcept
3664 {
3665 return static_cast<int_type>(c);
3666 }
3667
3669 {
3670 return static_cast<char_type>(i);
3671 }
3672
3673 static constexpr int_type eof() noexcept
3674 {
3675 return static_cast<int_type>(EOF);
3676 }
3677};
3678
3680// is_ functions //
3682
3683// https://en.cppreference.com/w/cpp/types/conjunction
3684template<class...> struct conjunction : std::true_type { };
3685template<class B> struct conjunction<B> : B { };
3686template<class B, class... Bn>
3687struct conjunction<B, Bn...>
3688: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3689
3690// https://en.cppreference.com/w/cpp/types/negation
3691template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3692
3693// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3694// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3695// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3696template <typename T>
3697struct is_default_constructible : std::is_default_constructible<T> {};
3698
3699template <typename T1, typename T2>
3700struct is_default_constructible<std::pair<T1, T2>>
3701 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3702
3703template <typename T1, typename T2>
3704struct is_default_constructible<const std::pair<T1, T2>>
3705 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3706
3707template <typename... Ts>
3708struct is_default_constructible<std::tuple<Ts...>>
3709 : conjunction<is_default_constructible<Ts>...> {};
3710
3711template <typename... Ts>
3712struct is_default_constructible<const std::tuple<Ts...>>
3713 : conjunction<is_default_constructible<Ts>...> {};
3714
3715template <typename T, typename... Args>
3716struct is_constructible : std::is_constructible<T, Args...> {};
3717
3718template <typename T1, typename T2>
3719struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3720
3721template <typename T1, typename T2>
3722struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3723
3724template <typename... Ts>
3725struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3726
3727template <typename... Ts>
3728struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3729
3730template<typename T, typename = void>
3731struct is_iterator_traits : std::false_type {};
3732
3733template<typename T>
3747
3748template<typename T>
3750{
3751 private:
3752 using t_ref = typename std::add_lvalue_reference<T>::type;
3753
3754 using iterator = detected_t<result_of_begin, t_ref>;
3755 using sentinel = detected_t<result_of_end, t_ref>;
3756
3757 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3758 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3759 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3760 static constexpr auto is_iterator_begin =
3762
3763 public:
3764 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3765};
3766
3767template<typename R>
3768using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3769
3770template<typename T>
3772
3773// The following implementation of is_complete_type is taken from
3774// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3775// and is written by Xiang Fan who agreed to using it in this library.
3776
3777template<typename T, typename = void>
3778struct is_complete_type : std::false_type {};
3779
3780template<typename T>
3781struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3782
3783template<typename BasicJsonType, typename CompatibleObjectType,
3784 typename = void>
3785struct is_compatible_object_type_impl : std::false_type {};
3786
3787template<typename BasicJsonType, typename CompatibleObjectType>
3789 BasicJsonType, CompatibleObjectType,
3790 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3791 is_detected<key_type_t, CompatibleObjectType>::value >>
3792{
3793 using object_t = typename BasicJsonType::object_t;
3794
3795 // macOS's is_constructible does not play well with nonesuch...
3796 static constexpr bool value =
3797 is_constructible<typename object_t::key_type,
3798 typename CompatibleObjectType::key_type>::value &&
3799 is_constructible<typename object_t::mapped_type,
3800 typename CompatibleObjectType::mapped_type>::value;
3801};
3802
3803template<typename BasicJsonType, typename CompatibleObjectType>
3805 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3806
3807template<typename BasicJsonType, typename ConstructibleObjectType,
3808 typename = void>
3809struct is_constructible_object_type_impl : std::false_type {};
3810
3811template<typename BasicJsonType, typename ConstructibleObjectType>
3813 BasicJsonType, ConstructibleObjectType,
3814 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3815 is_detected<key_type_t, ConstructibleObjectType>::value >>
3816{
3817 using object_t = typename BasicJsonType::object_t;
3818
3819 static constexpr bool value =
3821 (std::is_move_assignable<ConstructibleObjectType>::value ||
3822 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3823 (is_constructible<typename ConstructibleObjectType::key_type,
3824 typename object_t::key_type>::value &&
3825 std::is_same <
3826 typename object_t::mapped_type,
3827 typename ConstructibleObjectType::mapped_type >::value)) ||
3828 (has_from_json<BasicJsonType,
3829 typename ConstructibleObjectType::mapped_type>::value ||
3831 BasicJsonType,
3832 typename ConstructibleObjectType::mapped_type >::value);
3833};
3834
3835template<typename BasicJsonType, typename ConstructibleObjectType>
3837 : is_constructible_object_type_impl<BasicJsonType,
3838 ConstructibleObjectType> {};
3839
3840template<typename BasicJsonType, typename CompatibleStringType>
3846
3847template<typename BasicJsonType, typename ConstructibleStringType>
3849{
3850 // launder type through decltype() to fix compilation failure on ICPC
3851#ifdef __INTEL_COMPILER
3852 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3853#else
3854 using laundered_type = ConstructibleStringType;
3855#endif
3856
3857 static constexpr auto value =
3858 conjunction <
3860 is_detected_exact<typename BasicJsonType::string_t::value_type,
3862};
3863
3864template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3865struct is_compatible_array_type_impl : std::false_type {};
3866
3867template<typename BasicJsonType, typename CompatibleArrayType>
3869 BasicJsonType, CompatibleArrayType,
3870 enable_if_t <
3871 is_detected<iterator_t, CompatibleArrayType>::value&&
3872 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3873// special case for types like std::filesystem::path whose iterator's value_type are themselves
3874// c.f. https://github.com/nlohmann/json/pull/3073
3875 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3876{
3877 static constexpr bool value =
3878 is_constructible<BasicJsonType,
3880};
3881
3882template<typename BasicJsonType, typename CompatibleArrayType>
3884 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3885
3886template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3887struct is_constructible_array_type_impl : std::false_type {};
3888
3889template<typename BasicJsonType, typename ConstructibleArrayType>
3891 BasicJsonType, ConstructibleArrayType,
3892 enable_if_t<std::is_same<ConstructibleArrayType,
3893 typename BasicJsonType::value_type>::value >>
3894 : std::true_type {};
3895
3896template<typename BasicJsonType, typename ConstructibleArrayType>
3898 BasicJsonType, ConstructibleArrayType,
3899 enable_if_t < !std::is_same<ConstructibleArrayType,
3900 typename BasicJsonType::value_type>::value&&
3901 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3902 is_default_constructible<ConstructibleArrayType>::value&&
3903(std::is_move_assignable<ConstructibleArrayType>::value ||
3904 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3905is_detected<iterator_t, ConstructibleArrayType>::value&&
3906is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3907is_detected<range_value_t, ConstructibleArrayType>::value&&
3908// special case for types like std::filesystem::path whose iterator's value_type are themselves
3909// c.f. https://github.com/nlohmann/json/pull/3073
3910!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3912 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3913{
3915
3916 static constexpr bool value =
3917 std::is_same<value_type,
3918 typename BasicJsonType::array_t::value_type>::value ||
3919 has_from_json<BasicJsonType,
3922 BasicJsonType,
3924};
3925
3926template<typename BasicJsonType, typename ConstructibleArrayType>
3928 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3929
3930template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3931 typename = void>
3932struct is_compatible_integer_type_impl : std::false_type {};
3933
3934template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3936 RealIntegerType, CompatibleNumberIntegerType,
3937 enable_if_t < std::is_integral<RealIntegerType>::value&&
3938 std::is_integral<CompatibleNumberIntegerType>::value&&
3939 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3940{
3941 // is there an assert somewhere on overflows?
3942 using RealLimits = std::numeric_limits<RealIntegerType>;
3943 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3944
3945 static constexpr auto value =
3946 is_constructible<RealIntegerType,
3947 CompatibleNumberIntegerType>::value &&
3948 CompatibleLimits::is_integer &&
3949 RealLimits::is_signed == CompatibleLimits::is_signed;
3950};
3951
3952template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3954 : is_compatible_integer_type_impl<RealIntegerType,
3955 CompatibleNumberIntegerType> {};
3956
3957template<typename BasicJsonType, typename CompatibleType, typename = void>
3958struct is_compatible_type_impl: std::false_type {};
3959
3960template<typename BasicJsonType, typename CompatibleType>
3962 BasicJsonType, CompatibleType,
3963 enable_if_t<is_complete_type<CompatibleType>::value >>
3964{
3965 static constexpr bool value =
3967};
3968
3969template<typename BasicJsonType, typename CompatibleType>
3971 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3972
3973template<typename T1, typename T2>
3974struct is_constructible_tuple : std::false_type {};
3975
3976template<typename T1, typename... Args>
3977struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3978
3979template<typename BasicJsonType, typename T>
3980struct is_json_iterator_of : std::false_type {};
3981
3982template<typename BasicJsonType>
3983struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3984
3985template<typename BasicJsonType>
3986struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3987{};
3988
3989// checks if a given type T is a template specialization of Primary
3990template<template <typename...> class Primary, typename T>
3991struct is_specialization_of : std::false_type {};
3992
3993template<template <typename...> class Primary, typename... Args>
3994struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3995
3996template<typename T>
3998
3999// checks if A and B are comparable using Compare functor
4000template<typename Compare, typename A, typename B, typename = void>
4001struct is_comparable : std::false_type {};
4002
4003template<typename Compare, typename A, typename B>
4004struct is_comparable<Compare, A, B, void_t<
4005decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4006decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4007>> : std::true_type {};
4008
4009template<typename T>
4010using detect_is_transparent = typename T::is_transparent;
4011
4012// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4013// see is_usable_as_basic_json_key_type below
4014template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4015 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4016using is_usable_as_key_type = typename std::conditional <
4018 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4019 ObjectKeyType>::value)
4020 && (!RequireTransparentComparator
4021 || is_detected <detect_is_transparent, Comparator>::value)
4023 std::true_type,
4024 std::false_type >::type;
4025
4026// type trait to check if KeyType can be used as object key
4027// true if:
4028// - KeyType is comparable with BasicJsonType::object_t::key_type
4029// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4030// - the comparator is transparent or RequireTransparentComparator is false
4031// - KeyType is not a JSON iterator or json_pointer
4032template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4033 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4034using is_usable_as_basic_json_key_type = typename std::conditional <
4035 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4036 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4037 RequireTransparentComparator, ExcludeObjectKeyType>::value
4039 std::true_type,
4040 std::false_type >::type;
4041
4042template<typename ObjectType, typename KeyType>
4043using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4044
4045// type trait to check if object_t has an erase() member functions accepting KeyType
4046template<typename BasicJsonType, typename KeyType>
4047using has_erase_with_key_type = typename std::conditional <
4048 is_detected <
4050 typename BasicJsonType::object_t, KeyType >::value,
4051 std::true_type,
4052 std::false_type >::type;
4053
4054// a naive helper to check if a type is an ordered_map (exploits the fact that
4055// ordered_map inherits capacity() from std::vector)
4056template <typename T>
4058{
4059 using one = char;
4060
4061 struct two
4062 {
4063 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4064 };
4065
4066 template <typename C> static one test( decltype(&C::capacity) ) ;
4067 template <typename C> static two test(...);
4068
4069 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4070};
4071
4072// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4073template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4075{
4076 return static_cast<T>(value);
4077}
4078
4079template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4081{
4082 return value;
4083}
4084
4085template<typename... Types>
4087
4088template<typename... Types>
4090
4091template<typename... Types>
4093
4094// there's a disjunction trait in another PR; replace when merged
4095template<typename... Types>
4096using same_sign = std::integral_constant < bool,
4097 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4098
4099template<typename OfType, typename T>
4100using never_out_of_range = std::integral_constant < bool,
4101 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4102 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4103
4104template<typename OfType, typename T,
4105 bool OfTypeSigned = std::is_signed<OfType>::value,
4106 bool TSigned = std::is_signed<T>::value>
4108
4109template<typename OfType, typename T>
4110struct value_in_range_of_impl2<OfType, T, false, false>
4111{
4112 static constexpr bool test(T val)
4113 {
4114 using CommonType = typename std::common_type<OfType, T>::type;
4115 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4116 }
4117};
4118
4119template<typename OfType, typename T>
4120struct value_in_range_of_impl2<OfType, T, true, false>
4121{
4122 static constexpr bool test(T val)
4123 {
4124 using CommonType = typename std::common_type<OfType, T>::type;
4125 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4126 }
4127};
4128
4129template<typename OfType, typename T>
4130struct value_in_range_of_impl2<OfType, T, false, true>
4131{
4132 static constexpr bool test(T val)
4133 {
4134 using CommonType = typename std::common_type<OfType, T>::type;
4135 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4136 }
4137};
4138
4139template<typename OfType, typename T>
4140struct value_in_range_of_impl2<OfType, T, true, true>
4141{
4142 static constexpr bool test(T val)
4143 {
4144 using CommonType = typename std::common_type<OfType, T>::type;
4145 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4146 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4147 }
4148};
4149
4150template<typename OfType, typename T,
4151 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4154
4155template<typename OfType, typename T>
4156struct value_in_range_of_impl1<OfType, T, false>
4157{
4158 static constexpr bool test(T val)
4159 {
4161 }
4162};
4163
4164template<typename OfType, typename T>
4165struct value_in_range_of_impl1<OfType, T, true>
4166{
4167 static constexpr bool test(T /*val*/)
4168 {
4169 return true;
4170 }
4171};
4172
4173template<typename OfType, typename T>
4174inline constexpr bool value_in_range_of(T val)
4175{
4177}
4178
4179template<bool Value>
4180using bool_constant = std::integral_constant<bool, Value>;
4181
4183// is_c_string
4185
4186namespace impl
4187{
4188
4189template<typename T>
4190inline constexpr bool is_c_string()
4191{
4192 using TUnExt = typename std::remove_extent<T>::type;
4193 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4194 using TUnPtr = typename std::remove_pointer<T>::type;
4195 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4196 return
4197 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4198 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4199}
4200
4201} // namespace impl
4202
4203// checks whether T is a [cv] char */[cv] char[] C string
4204template<typename T>
4205struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4206
4207template<typename T>
4209
4211// is_transparent
4213
4214namespace impl
4215{
4216
4217template<typename T>
4218inline constexpr bool is_transparent()
4219{
4221}
4222
4223} // namespace impl
4224
4225// checks whether T has a member named is_transparent
4226template<typename T>
4227struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4228
4230
4231} // namespace detail
4233
4234// #include <nlohmann/detail/string_concat.hpp>
4235// __ _____ _____ _____
4236// __| | __| | | | JSON for Modern C++
4237// | | |__ | | | | | | version 3.11.3
4238// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4239//
4240// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4241// SPDX-License-Identifier: MIT
4242
4243
4244
4245#include <cstring> // strlen
4246#include <string> // string
4247#include <utility> // forward
4248
4249// #include <nlohmann/detail/meta/cpp_future.hpp>
4250
4251// #include <nlohmann/detail/meta/detected.hpp>
4252
4253
4255namespace detail
4256{
4257
4258inline std::size_t concat_length()
4259{
4260 return 0;
4261}
4262
4263template<typename... Args>
4264inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4265
4266template<typename StringType, typename... Args>
4267inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4268
4269template<typename... Args>
4270inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4271{
4272 return 1 + concat_length(rest...);
4273}
4274
4275template<typename... Args>
4276inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4277{
4278 // cppcheck-suppress ignoredReturnValue
4279 return ::strlen(cstr) + concat_length(rest...);
4280}
4281
4282template<typename StringType, typename... Args>
4283inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4284{
4285 return str.size() + concat_length(rest...);
4286}
4287
4288template<typename OutStringType>
4289inline void concat_into(OutStringType& /*out*/)
4290{}
4291
4292template<typename StringType, typename Arg>
4293using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4294
4295template<typename StringType, typename Arg>
4297
4298template<typename StringType, typename Arg>
4299using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4300
4301template<typename StringType, typename Arg>
4303
4304template<typename StringType, typename Arg>
4305using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4306
4307template<typename StringType, typename Arg>
4309
4310template<typename StringType, typename Arg>
4311using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4312
4313template<typename StringType, typename Arg>
4315
4316template < typename OutStringType, typename Arg, typename... Args,
4317 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4319inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4320
4321template < typename OutStringType, typename Arg, typename... Args,
4322 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4325inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4326
4327template < typename OutStringType, typename Arg, typename... Args,
4328 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4332inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4333
4334template<typename OutStringType, typename Arg, typename... Args,
4336inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4337{
4338 out.append(std::forward<Arg>(arg));
4339 concat_into(out, std::forward<Args>(rest)...);
4340}
4341
4342template < typename OutStringType, typename Arg, typename... Args,
4343 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4344 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4345inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4346{
4347 out += std::forward<Arg>(arg);
4348 concat_into(out, std::forward<Args>(rest)...);
4349}
4350
4351template < typename OutStringType, typename Arg, typename... Args,
4352 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4353 && !detect_string_can_append_op<OutStringType, Arg>::value
4354 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4355inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4356{
4357 out.append(arg.begin(), arg.end());
4358 concat_into(out, std::forward<Args>(rest)...);
4359}
4360
4361template < typename OutStringType, typename Arg, typename... Args,
4362 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4363 && !detect_string_can_append_op<OutStringType, Arg>::value
4364 && !detect_string_can_append_iter<OutStringType, Arg>::value
4365 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4366inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4367{
4368 out.append(arg.data(), arg.size());
4369 concat_into(out, std::forward<Args>(rest)...);
4370}
4371
4372template<typename OutStringType = std::string, typename... Args>
4373inline OutStringType concat(Args && ... args)
4374{
4375 OutStringType str;
4376 str.reserve(concat_length(args...));
4377 concat_into(str, std::forward<Args>(args)...);
4378 return str;
4379}
4380
4381} // namespace detail
4383
4384
4386namespace detail
4387{
4388
4390// exceptions //
4392
4395class exception : public std::exception
4396{
4397 public:
4399 const char* what() const noexcept override
4400 {
4401 return m.what();
4402 }
4403
4405 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4406
4407 protected:
4409 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4410
4411 static std::string name(const std::string& ename, int id_)
4412 {
4413 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4414 }
4415
4416 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4417 {
4418 return "";
4419 }
4420
4421 template<typename BasicJsonType>
4422 static std::string diagnostics(const BasicJsonType* leaf_element)
4423 {
4424#if JSON_DIAGNOSTICS
4425 std::vector<std::string> tokens;
4426 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4427 {
4428 switch (current->m_parent->type())
4429 {
4430 case value_t::array:
4431 {
4432 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4433 {
4434 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4435 {
4436 tokens.emplace_back(std::to_string(i));
4437 break;
4438 }
4439 }
4440 break;
4441 }
4442
4443 case value_t::object:
4444 {
4445 for (const auto& element : *current->m_parent->m_data.m_value.object)
4446 {
4447 if (&element.second == current)
4448 {
4449 tokens.emplace_back(element.first.c_str());
4450 break;
4451 }
4452 }
4453 break;
4454 }
4455
4456 case value_t::null: // LCOV_EXCL_LINE
4457 case value_t::string: // LCOV_EXCL_LINE
4458 case value_t::boolean: // LCOV_EXCL_LINE
4459 case value_t::number_integer: // LCOV_EXCL_LINE
4460 case value_t::number_unsigned: // LCOV_EXCL_LINE
4461 case value_t::number_float: // LCOV_EXCL_LINE
4462 case value_t::binary: // LCOV_EXCL_LINE
4463 case value_t::discarded: // LCOV_EXCL_LINE
4464 default: // LCOV_EXCL_LINE
4465 break; // LCOV_EXCL_LINE
4466 }
4467 }
4468
4469 if (tokens.empty())
4470 {
4471 return "";
4472 }
4473
4474 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4475 [](const std::string & a, const std::string & b)
4476 {
4477 return concat(a, '/', detail::escape(b));
4478 });
4479 return concat('(', str, ") ");
4480#else
4481 static_cast<void>(leaf_element);
4482 return "";
4483#endif
4484 }
4485
4486 private:
4488 std::runtime_error m;
4489};
4490
4494{
4495 public:
4505 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4506 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4507 {
4508 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4509 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4510 return {id_, pos.chars_read_total, w.c_str()};
4511 }
4512
4513 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4514 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4515 {
4516 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4517 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4518 ": ", exception::diagnostics(context), what_arg);
4519 return {id_, byte_, w.c_str()};
4520 }
4521
4531 const std::size_t byte;
4532
4533 private:
4534 parse_error(int id_, std::size_t byte_, const char* what_arg)
4535 : exception(id_, what_arg), byte(byte_) {}
4536
4537 static std::string position_string(const position_t& pos)
4538 {
4539 return concat(" at line ", std::to_string(pos.lines_read + 1),
4540 ", column ", std::to_string(pos.chars_read_current_line));
4541 }
4542};
4543
4547{
4548 public:
4549 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4550 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4551 {
4552 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4553 return {id_, w.c_str()};
4554 }
4555
4556 private:
4558 invalid_iterator(int id_, const char* what_arg)
4559 : exception(id_, what_arg) {}
4560};
4561
4564class type_error : public exception
4565{
4566 public:
4567 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4568 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4569 {
4570 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4571 return {id_, w.c_str()};
4572 }
4573
4574 private:
4576 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4577};
4578
4582{
4583 public:
4584 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4585 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4586 {
4587 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4588 return {id_, w.c_str()};
4589 }
4590
4591 private:
4593 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4594};
4595
4599{
4600 public:
4601 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4602 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4603 {
4604 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4605 return {id_, w.c_str()};
4606 }
4607
4608 private:
4610 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4611};
4612
4613} // namespace detail
4615
4616// #include <nlohmann/detail/macro_scope.hpp>
4617
4618// #include <nlohmann/detail/meta/cpp_future.hpp>
4619
4620// #include <nlohmann/detail/meta/identity_tag.hpp>
4621// __ _____ _____ _____
4622// __| | __| | | | JSON for Modern C++
4623// | | |__ | | | | | | version 3.11.3
4624// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4625//
4626// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4627// SPDX-License-Identifier: MIT
4628
4629
4630
4631// #include <nlohmann/detail/abi_macros.hpp>
4632
4633
4635namespace detail
4636{
4637
4638// dispatching helper struct
4639template <class T> struct identity_tag {};
4640
4641} // namespace detail
4643
4644// #include <nlohmann/detail/meta/std_fs.hpp>
4645// __ _____ _____ _____
4646// __| | __| | | | JSON for Modern C++
4647// | | |__ | | | | | | version 3.11.3
4648// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4649//
4650// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4651// SPDX-License-Identifier: MIT
4652
4653
4654
4655// #include <nlohmann/detail/macro_scope.hpp>
4656
4657
4658#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4659#include <experimental/filesystem>
4661namespace detail
4662{
4663namespace std_fs = std::experimental::filesystem;
4664} // namespace detail
4666#elif JSON_HAS_FILESYSTEM
4667#include <filesystem>
4669namespace detail
4670{
4671namespace std_fs = std::filesystem;
4672} // namespace detail
4674#endif
4675
4676// #include <nlohmann/detail/meta/type_traits.hpp>
4677
4678// #include <nlohmann/detail/string_concat.hpp>
4679
4680// #include <nlohmann/detail/value_t.hpp>
4681
4682
4684namespace detail
4685{
4686
4687template<typename BasicJsonType>
4688inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4689{
4690 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4691 {
4692 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4693 }
4694 n = nullptr;
4695}
4696
4697// overloads for basic_json template parameters
4698template < typename BasicJsonType, typename ArithmeticType,
4699 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4700 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4701 int > = 0 >
4702void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4703{
4704 switch (static_cast<value_t>(j))
4705 {
4707 {
4708 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4709 break;
4710 }
4712 {
4713 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4714 break;
4715 }
4717 {
4718 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4719 break;
4720 }
4721
4722 case value_t::null:
4723 case value_t::object:
4724 case value_t::array:
4725 case value_t::string:
4726 case value_t::boolean:
4727 case value_t::binary:
4728 case value_t::discarded:
4729 default:
4730 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4731 }
4732}
4733
4734template<typename BasicJsonType>
4735inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4736{
4737 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4738 {
4739 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4740 }
4741 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4742}
4743
4744template<typename BasicJsonType>
4745inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4746{
4747 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4748 {
4749 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4750 }
4751 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4752}
4753
4754template <
4755 typename BasicJsonType, typename StringType,
4756 enable_if_t <
4757 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4758 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4759 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4760 && !is_json_ref<StringType>::value, int > = 0 >
4761inline void from_json(const BasicJsonType& j, StringType& s)
4762{
4763 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4764 {
4765 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4766 }
4767
4768 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4769}
4770
4771template<typename BasicJsonType>
4772inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4773{
4774 get_arithmetic_value(j, val);
4775}
4776
4777template<typename BasicJsonType>
4778inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4779{
4780 get_arithmetic_value(j, val);
4781}
4782
4783template<typename BasicJsonType>
4784inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4785{
4786 get_arithmetic_value(j, val);
4787}
4788
4789#if !JSON_DISABLE_ENUM_SERIALIZATION
4790template<typename BasicJsonType, typename EnumType,
4791 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4792inline void from_json(const BasicJsonType& j, EnumType& e)
4793{
4794 typename std::underlying_type<EnumType>::type val;
4795 get_arithmetic_value(j, val);
4796 e = static_cast<EnumType>(val);
4797}
4798#endif // JSON_DISABLE_ENUM_SERIALIZATION
4799
4800// forward_list doesn't have an insert method
4801template<typename BasicJsonType, typename T, typename Allocator,
4802 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4803inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4804{
4805 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4806 {
4807 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4808 }
4809 l.clear();
4810 std::transform(j.rbegin(), j.rend(),
4811 std::front_inserter(l), [](const BasicJsonType & i)
4812 {
4813 return i.template get<T>();
4814 });
4815}
4816
4817// valarray doesn't have an insert method
4818template<typename BasicJsonType, typename T,
4819 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4820inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4821{
4822 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4823 {
4824 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4825 }
4826 l.resize(j.size());
4827 std::transform(j.begin(), j.end(), std::begin(l),
4828 [](const BasicJsonType & elem)
4829 {
4830 return elem.template get<T>();
4831 });
4832}
4833
4834template<typename BasicJsonType, typename T, std::size_t N>
4835auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4836-> decltype(j.template get<T>(), void())
4837{
4838 for (std::size_t i = 0; i < N; ++i)
4839 {
4840 arr[i] = j.at(i).template get<T>();
4841 }
4842}
4843
4844template<typename BasicJsonType>
4845inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4846{
4847 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4848}
4849
4850template<typename BasicJsonType, typename T, std::size_t N>
4851auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4852 priority_tag<2> /*unused*/)
4853-> decltype(j.template get<T>(), void())
4854{
4855 for (std::size_t i = 0; i < N; ++i)
4856 {
4857 arr[i] = j.at(i).template get<T>();
4858 }
4859}
4860
4861template<typename BasicJsonType, typename ConstructibleArrayType,
4863 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4864 int> = 0>
4865auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4866-> decltype(
4867 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4869 void())
4870{
4871 using std::end;
4872
4873 ConstructibleArrayType ret;
4874 ret.reserve(j.size());
4875 std::transform(j.begin(), j.end(),
4876 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4877 {
4878 // get<BasicJsonType>() returns *this, this won't call a from_json
4879 // method when value_type is BasicJsonType
4881 });
4882 arr = std::move(ret);
4883}
4884
4885template<typename BasicJsonType, typename ConstructibleArrayType,
4887 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4888 int> = 0>
4889inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4890 priority_tag<0> /*unused*/)
4891{
4892 using std::end;
4893
4894 ConstructibleArrayType ret;
4895 std::transform(
4896 j.begin(), j.end(), std::inserter(ret, end(ret)),
4897 [](const BasicJsonType & i)
4898 {
4899 // get<BasicJsonType>() returns *this, this won't call a from_json
4900 // method when value_type is BasicJsonType
4902 });
4903 arr = std::move(ret);
4904}
4905
4906template < typename BasicJsonType, typename ConstructibleArrayType,
4907 enable_if_t <
4908 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4909 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4911 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4912 !is_basic_json<ConstructibleArrayType>::value,
4913 int > = 0 >
4914auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4915-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4917void())
4918{
4919 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4920 {
4921 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4922 }
4923
4924 from_json_array_impl(j, arr, priority_tag<3> {});
4925}
4926
4927template < typename BasicJsonType, typename T, std::size_t... Idx >
4928std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4929 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4930{
4931 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4932}
4933
4934template < typename BasicJsonType, typename T, std::size_t N >
4935auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4936-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4937{
4938 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4939 {
4940 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4941 }
4942
4943 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4944}
4945
4946template<typename BasicJsonType>
4947inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4948{
4949 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4950 {
4951 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4952 }
4953
4954 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4955}
4956
4957template<typename BasicJsonType, typename ConstructibleObjectType,
4958 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4959inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4960{
4961 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4962 {
4963 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4964 }
4965
4966 ConstructibleObjectType ret;
4967 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4968 using value_type = typename ConstructibleObjectType::value_type;
4969 std::transform(
4970 inner_object->begin(), inner_object->end(),
4971 std::inserter(ret, ret.begin()),
4972 [](typename BasicJsonType::object_t::value_type const & p)
4973 {
4974 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4975 });
4976 obj = std::move(ret);
4977}
4978
4979// overload for arithmetic types, not chosen for basic_json template arguments
4980// (BooleanType, etc..); note: Is it really necessary to provide explicit
4981// overloads for boolean_t etc. in case of a custom BooleanType which is not
4982// an arithmetic type?
4983template < typename BasicJsonType, typename ArithmeticType,
4984 enable_if_t <
4985 std::is_arithmetic<ArithmeticType>::value&&
4986 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4987 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4988 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4989 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4990 int > = 0 >
4991inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4992{
4993 switch (static_cast<value_t>(j))
4994 {
4996 {
4997 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4998 break;
4999 }
5001 {
5002 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5003 break;
5004 }
5006 {
5007 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5008 break;
5009 }
5010 case value_t::boolean:
5011 {
5012 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5013 break;
5014 }
5015
5016 case value_t::null:
5017 case value_t::object:
5018 case value_t::array:
5019 case value_t::string:
5020 case value_t::binary:
5021 case value_t::discarded:
5022 default:
5023 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5024 }
5025}
5026
5027template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5028std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5029{
5030 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5031}
5032
5033template < typename BasicJsonType, class A1, class A2 >
5034std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5035{
5036 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5037 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5038}
5039
5040template<typename BasicJsonType, typename A1, typename A2>
5041inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5042{
5043 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5044}
5045
5046template<typename BasicJsonType, typename... Args>
5047std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5048{
5049 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5050}
5051
5052template<typename BasicJsonType, typename... Args>
5053inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5054{
5055 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5056}
5057
5058template<typename BasicJsonType, typename TupleRelated>
5059auto from_json(BasicJsonType&& j, TupleRelated&& t)
5060-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5061{
5062 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5063 {
5064 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5065 }
5066
5067 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5068}
5069
5070template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5071 typename = enable_if_t < !std::is_constructible <
5072 typename BasicJsonType::string_t, Key >::value >>
5073inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5074{
5075 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5076 {
5077 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5078 }
5079 m.clear();
5080 for (const auto& p : j)
5081 {
5082 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5083 {
5084 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5085 }
5086 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5087 }
5088}
5089
5090template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5091 typename = enable_if_t < !std::is_constructible <
5092 typename BasicJsonType::string_t, Key >::value >>
5093inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5094{
5095 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5096 {
5097 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5098 }
5099 m.clear();
5100 for (const auto& p : j)
5101 {
5102 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5103 {
5104 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5105 }
5106 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5107 }
5108}
5109
5110#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5111template<typename BasicJsonType>
5112inline void from_json(const BasicJsonType& j, std_fs::path& p)
5113{
5114 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5115 {
5116 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5117 }
5118 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5119}
5120#endif
5121
5123{
5124 template<typename BasicJsonType, typename T>
5125 auto operator()(const BasicJsonType& j, T&& val) const
5126 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5127 -> decltype(from_json(j, std::forward<T>(val)))
5128 {
5129 return from_json(j, std::forward<T>(val));
5130 }
5131};
5132
5133} // namespace detail
5134
5135#ifndef JSON_HAS_CPP_17
5139namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5140{
5141#endif
5142JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5144#ifndef JSON_HAS_CPP_17
5145} // namespace
5146#endif
5147
5149
5150// #include <nlohmann/detail/conversions/to_json.hpp>
5151// __ _____ _____ _____
5152// __| | __| | | | JSON for Modern C++
5153// | | |__ | | | | | | version 3.11.3
5154// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5155//
5156// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5157// SPDX-License-Identifier: MIT
5158
5159
5160
5161#include <algorithm> // copy
5162#include <iterator> // begin, end
5163#include <string> // string
5164#include <tuple> // tuple, get
5165#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5166#include <utility> // move, forward, declval, pair
5167#include <valarray> // valarray
5168#include <vector> // vector
5169
5170// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5171// __ _____ _____ _____
5172// __| | __| | | | JSON for Modern C++
5173// | | |__ | | | | | | version 3.11.3
5174// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5175//
5176// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5177// SPDX-License-Identifier: MIT
5178
5179
5180
5181#include <cstddef> // size_t
5182#include <iterator> // input_iterator_tag
5183#include <string> // string, to_string
5184#include <tuple> // tuple_size, get, tuple_element
5185#include <utility> // move
5186
5187#if JSON_HAS_RANGES
5188 #include <ranges> // enable_borrowed_range
5189#endif
5190
5191// #include <nlohmann/detail/abi_macros.hpp>
5192
5193// #include <nlohmann/detail/meta/type_traits.hpp>
5194
5195// #include <nlohmann/detail/value_t.hpp>
5196
5197
5199namespace detail
5200{
5201
5202template<typename string_type>
5203void int_to_string( string_type& target, std::size_t value )
5204{
5205 // For ADL
5206 using std::to_string;
5207 target = to_string(value);
5208}
5209template<typename IteratorType> class iteration_proxy_value
5210{
5211 public:
5212 using difference_type = std::ptrdiff_t;
5216 using iterator_category = std::input_iterator_tag;
5217 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5218
5219 private:
5221 IteratorType anchor{};
5223 std::size_t array_index = 0;
5225 mutable std::size_t array_index_last = 0;
5227 mutable string_type array_index_str = "0";
5229 string_type empty_str{};
5230
5231 public:
5232 explicit iteration_proxy_value() = default;
5233 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5234 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5235 && std::is_nothrow_default_constructible<string_type>::value)
5236 : anchor(std::move(it))
5237 , array_index(array_index_)
5238 {}
5239
5242 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5244 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5245 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5247 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5248 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5250
5252 const iteration_proxy_value& operator*() const
5253 {
5254 return *this;
5255 }
5256
5259 {
5260 ++anchor;
5261 ++array_index;
5262
5263 return *this;
5264 }
5265
5266 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5267 {
5268 auto tmp = iteration_proxy_value(anchor, array_index);
5269 ++anchor;
5270 ++array_index;
5271 return tmp;
5272 }
5273
5276 {
5277 return anchor == o.anchor;
5278 }
5279
5282 {
5283 return anchor != o.anchor;
5284 }
5285
5287 const string_type& key() const
5288 {
5289 JSON_ASSERT(anchor.m_object != nullptr);
5290
5291 switch (anchor.m_object->type())
5292 {
5293 // use integer array index as key
5294 case value_t::array:
5295 {
5296 if (array_index != array_index_last)
5297 {
5298 int_to_string( array_index_str, array_index );
5299 array_index_last = array_index;
5300 }
5301 return array_index_str;
5302 }
5303
5304 // use key from the object
5305 case value_t::object:
5306 return anchor.key();
5307
5308 // use an empty key for all primitive types
5309 case value_t::null:
5310 case value_t::string:
5311 case value_t::boolean:
5315 case value_t::binary:
5316 case value_t::discarded:
5317 default:
5318 return empty_str;
5319 }
5320 }
5321
5323 typename IteratorType::reference value() const
5324 {
5325 return anchor.value();
5326 }
5327};
5328
5330template<typename IteratorType> class iteration_proxy
5331{
5332 private:
5334 typename IteratorType::pointer container = nullptr;
5335
5336 public:
5337 explicit iteration_proxy() = default;
5338
5340 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5341 : container(&cont) {}
5342
5345 iteration_proxy(iteration_proxy&&) noexcept = default;
5346 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5347 ~iteration_proxy() = default;
5348
5350 iteration_proxy_value<IteratorType> begin() const noexcept
5351 {
5352 return iteration_proxy_value<IteratorType>(container->begin());
5353 }
5354
5357 {
5358 return iteration_proxy_value<IteratorType>(container->end());
5359 }
5360};
5361
5362// Structured Bindings Support
5363// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5364// And see https://github.com/nlohmann/json/pull/1391
5365template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5366auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5367{
5368 return i.key();
5369}
5370// Structured Bindings Support
5371// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5372// And see https://github.com/nlohmann/json/pull/1391
5373template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5374auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5375{
5376 return i.value();
5377}
5378
5379} // namespace detail
5381
5382// The Addition to the STD Namespace is required to add
5383// Structured Bindings Support to the iteration_proxy_value class
5384// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5385// And see https://github.com/nlohmann/json/pull/1391
5386namespace std
5387{
5388
5389#if defined(__clang__)
5390 // Fix: https://github.com/nlohmann/json/issues/1401
5391 #pragma clang diagnostic push
5392 #pragma clang diagnostic ignored "-Wmismatched-tags"
5393#endif
5394template<typename IteratorType>
5395class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5396 : public std::integral_constant<std::size_t, 2> {};
5397
5398template<std::size_t N, typename IteratorType>
5399class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5400{
5401 public:
5402 using type = decltype(
5403 get<N>(std::declval <
5404 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5405};
5406#if defined(__clang__)
5407 #pragma clang diagnostic pop
5408#endif
5409
5410} // namespace std
5411
5412#if JSON_HAS_RANGES
5413 template <typename IteratorType>
5414 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5415#endif
5416
5417// #include <nlohmann/detail/macro_scope.hpp>
5418
5419// #include <nlohmann/detail/meta/cpp_future.hpp>
5420
5421// #include <nlohmann/detail/meta/std_fs.hpp>
5422
5423// #include <nlohmann/detail/meta/type_traits.hpp>
5424
5425// #include <nlohmann/detail/value_t.hpp>
5426
5427
5429namespace detail
5430{
5431
5433// constructors //
5435
5436/*
5437 * Note all external_constructor<>::construct functions need to call
5438 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5439 * allocated value (e.g., a string). See bug issue
5440 * https://github.com/nlohmann/json/issues/2865 for more information.
5441 */
5442
5443template<value_t> struct external_constructor;
5444
5445template<>
5447{
5448 template<typename BasicJsonType>
5449 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5450 {
5451 j.m_data.m_value.destroy(j.m_data.m_type);
5452 j.m_data.m_type = value_t::boolean;
5453 j.m_data.m_value = b;
5454 j.assert_invariant();
5455 }
5456};
5457
5458template<>
5460{
5461 template<typename BasicJsonType>
5462 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5463 {
5464 j.m_data.m_value.destroy(j.m_data.m_type);
5465 j.m_data.m_type = value_t::string;
5466 j.m_data.m_value = s;
5467 j.assert_invariant();
5468 }
5469
5470 template<typename BasicJsonType>
5471 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5472 {
5473 j.m_data.m_value.destroy(j.m_data.m_type);
5474 j.m_data.m_type = value_t::string;
5475 j.m_data.m_value = std::move(s);
5476 j.assert_invariant();
5477 }
5478
5479 template < typename BasicJsonType, typename CompatibleStringType,
5480 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5481 int > = 0 >
5482 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5483 {
5484 j.m_data.m_value.destroy(j.m_data.m_type);
5485 j.m_data.m_type = value_t::string;
5486 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5487 j.assert_invariant();
5488 }
5489};
5490
5491template<>
5493{
5494 template<typename BasicJsonType>
5495 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5496 {
5497 j.m_data.m_value.destroy(j.m_data.m_type);
5498 j.m_data.m_type = value_t::binary;
5499 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5500 j.assert_invariant();
5501 }
5502
5503 template<typename BasicJsonType>
5504 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5505 {
5506 j.m_data.m_value.destroy(j.m_data.m_type);
5507 j.m_data.m_type = value_t::binary;
5508 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5509 j.assert_invariant();
5510 }
5511};
5512
5513template<>
5515{
5516 template<typename BasicJsonType>
5517 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5518 {
5519 j.m_data.m_value.destroy(j.m_data.m_type);
5520 j.m_data.m_type = value_t::number_float;
5521 j.m_data.m_value = val;
5522 j.assert_invariant();
5523 }
5524};
5525
5526template<>
5528{
5529 template<typename BasicJsonType>
5530 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5531 {
5532 j.m_data.m_value.destroy(j.m_data.m_type);
5533 j.m_data.m_type = value_t::number_unsigned;
5534 j.m_data.m_value = val;
5535 j.assert_invariant();
5536 }
5537};
5538
5539template<>
5541{
5542 template<typename BasicJsonType>
5543 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5544 {
5545 j.m_data.m_value.destroy(j.m_data.m_type);
5546 j.m_data.m_type = value_t::number_integer;
5547 j.m_data.m_value = val;
5548 j.assert_invariant();
5549 }
5550};
5551
5552template<>
5554{
5555 template<typename BasicJsonType>
5556 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5557 {
5558 j.m_data.m_value.destroy(j.m_data.m_type);
5559 j.m_data.m_type = value_t::array;
5560 j.m_data.m_value = arr;
5561 j.set_parents();
5562 j.assert_invariant();
5563 }
5564
5565 template<typename BasicJsonType>
5566 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5567 {
5568 j.m_data.m_value.destroy(j.m_data.m_type);
5569 j.m_data.m_type = value_t::array;
5570 j.m_data.m_value = std::move(arr);
5571 j.set_parents();
5572 j.assert_invariant();
5573 }
5574
5575 template < typename BasicJsonType, typename CompatibleArrayType,
5576 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5577 int > = 0 >
5578 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5579 {
5580 using std::begin;
5581 using std::end;
5582
5583 j.m_data.m_value.destroy(j.m_data.m_type);
5584 j.m_data.m_type = value_t::array;
5585 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5586 j.set_parents();
5587 j.assert_invariant();
5588 }
5589
5590 template<typename BasicJsonType>
5591 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5592 {
5593 j.m_data.m_value.destroy(j.m_data.m_type);
5594 j.m_data.m_type = value_t::array;
5595 j.m_data.m_value = value_t::array;
5596 j.m_data.m_value.array->reserve(arr.size());
5597 for (const bool x : arr)
5598 {
5599 j.m_data.m_value.array->push_back(x);
5600 j.set_parent(j.m_data.m_value.array->back());
5601 }
5602 j.assert_invariant();
5603 }
5604
5605 template<typename BasicJsonType, typename T,
5607 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5608 {
5609 j.m_data.m_value.destroy(j.m_data.m_type);
5610 j.m_data.m_type = value_t::array;
5611 j.m_data.m_value = value_t::array;
5612 j.m_data.m_value.array->resize(arr.size());
5613 if (arr.size() > 0)
5614 {
5615 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5616 }
5617 j.set_parents();
5618 j.assert_invariant();
5619 }
5620};
5621
5622template<>
5624{
5625 template<typename BasicJsonType>
5626 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5627 {
5628 j.m_data.m_value.destroy(j.m_data.m_type);
5629 j.m_data.m_type = value_t::object;
5630 j.m_data.m_value = obj;
5631 j.set_parents();
5632 j.assert_invariant();
5633 }
5634
5635 template<typename BasicJsonType>
5636 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5637 {
5638 j.m_data.m_value.destroy(j.m_data.m_type);
5639 j.m_data.m_type = value_t::object;
5640 j.m_data.m_value = std::move(obj);
5641 j.set_parents();
5642 j.assert_invariant();
5643 }
5644
5645 template < typename BasicJsonType, typename CompatibleObjectType,
5646 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5647 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5648 {
5649 using std::begin;
5650 using std::end;
5651
5652 j.m_data.m_value.destroy(j.m_data.m_type);
5653 j.m_data.m_type = value_t::object;
5654 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5655 j.set_parents();
5656 j.assert_invariant();
5657 }
5658};
5659
5661// to_json //
5663
5664template<typename BasicJsonType, typename T,
5665 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5666inline void to_json(BasicJsonType& j, T b) noexcept
5667{
5669}
5670
5671template < typename BasicJsonType, typename BoolRef,
5672 enable_if_t <
5673 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5674 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5675 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5676 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5677 typename BasicJsonType::boolean_t >::value))
5678 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5679inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5680{
5681 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5682}
5683
5684template<typename BasicJsonType, typename CompatibleString,
5685 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5686inline void to_json(BasicJsonType& j, const CompatibleString& s)
5687{
5689}
5690
5691template<typename BasicJsonType>
5692inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5693{
5695}
5696
5697template<typename BasicJsonType, typename FloatType,
5698 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5699inline void to_json(BasicJsonType& j, FloatType val) noexcept
5700{
5701 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5702}
5703
5704template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5705 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5706inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5707{
5708 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5709}
5710
5711template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5712 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5713inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5714{
5715 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5716}
5717
5718#if !JSON_DISABLE_ENUM_SERIALIZATION
5719template<typename BasicJsonType, typename EnumType,
5720 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5721inline void to_json(BasicJsonType& j, EnumType e) noexcept
5722{
5723 using underlying_type = typename std::underlying_type<EnumType>::type;
5724 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5725}
5726#endif // JSON_DISABLE_ENUM_SERIALIZATION
5727
5728template<typename BasicJsonType>
5729inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5730{
5732}
5733
5734template < typename BasicJsonType, typename CompatibleArrayType,
5735 enable_if_t < is_compatible_array_type<BasicJsonType,
5736 CompatibleArrayType>::value&&
5737 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5739 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5740 !is_basic_json<CompatibleArrayType>::value,
5741 int > = 0 >
5742inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5743{
5745}
5746
5747template<typename BasicJsonType>
5748inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5749{
5751}
5752
5753template<typename BasicJsonType, typename T,
5754 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5755inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5756{
5758}
5759
5760template<typename BasicJsonType>
5761inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5762{
5764}
5765
5766template < typename BasicJsonType, typename CompatibleObjectType,
5767 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5768inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5769{
5771}
5772
5773template<typename BasicJsonType>
5774inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5775{
5777}
5778
5779template <
5780 typename BasicJsonType, typename T, std::size_t N,
5781 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5782 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5783 int > = 0 >
5784inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5785{
5787}
5788
5789template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5790inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5791{
5792 j = { p.first, p.second };
5793}
5794
5795// for https://github.com/nlohmann/json/pull/1134
5796template<typename BasicJsonType, typename T,
5798inline void to_json(BasicJsonType& j, const T& b)
5799{
5800 j = { {b.key(), b.value()} };
5801}
5802
5803template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5804inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5805{
5806 j = { std::get<Idx>(t)... };
5807}
5808
5809template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5810inline void to_json(BasicJsonType& j, const T& t)
5811{
5812 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5813}
5814
5815#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5816template<typename BasicJsonType>
5817inline void to_json(BasicJsonType& j, const std_fs::path& p)
5818{
5819 j = p.string();
5820}
5821#endif
5822
5824{
5825 template<typename BasicJsonType, typename T>
5826 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5827 -> decltype(to_json(j, std::forward<T>(val)), void())
5828 {
5829 return to_json(j, std::forward<T>(val));
5830 }
5831};
5832} // namespace detail
5833
5834#ifndef JSON_HAS_CPP_17
5838namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5839{
5840#endif
5841JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5843#ifndef JSON_HAS_CPP_17
5844} // namespace
5845#endif
5846
5848
5849// #include <nlohmann/detail/meta/identity_tag.hpp>
5850
5851
5853
5855template<typename ValueType, typename>
5857{
5860 template<typename BasicJsonType, typename TargetType = ValueType>
5861 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5862 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5863 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5864 {
5865 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5866 }
5867
5870 template<typename BasicJsonType, typename TargetType = ValueType>
5871 static auto from_json(BasicJsonType && j) noexcept(
5872 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5873 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5874 {
5875 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5876 }
5877
5880 template<typename BasicJsonType, typename TargetType = ValueType>
5881 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5882 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5883 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5884 {
5885 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5886 }
5887};
5888
5890
5891// #include <nlohmann/byte_container_with_subtype.hpp>
5892// __ _____ _____ _____
5893// __| | __| | | | JSON for Modern C++
5894// | | |__ | | | | | | version 3.11.3
5895// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5896//
5897// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5898// SPDX-License-Identifier: MIT
5899
5900
5901
5902#include <cstdint> // uint8_t, uint64_t
5903#include <tuple> // tie
5904#include <utility> // move
5905
5906// #include <nlohmann/detail/abi_macros.hpp>
5907
5908
5910
5913template<typename BinaryType>
5914class byte_container_with_subtype : public BinaryType
5915{
5916 public:
5917 using container_type = BinaryType;
5918 using subtype_type = std::uint64_t;
5919
5922 : container_type()
5923 {}
5924
5927 : container_type(b)
5928 {}
5929
5931 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5932 : container_type(std::move(b))
5933 {}
5934
5937 : container_type(b)
5938 , m_subtype(subtype_)
5939 , m_has_subtype(true)
5940 {}
5941
5943 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5944 : container_type(std::move(b))
5945 , m_subtype(subtype_)
5946 , m_has_subtype(true)
5947 {}
5948
5950 {
5951 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5952 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5953 }
5954
5956 {
5957 return !(rhs == *this);
5958 }
5959
5962 void set_subtype(subtype_type subtype_) noexcept
5963 {
5964 m_subtype = subtype_;
5965 m_has_subtype = true;
5966 }
5967
5970 constexpr subtype_type subtype() const noexcept
5971 {
5972 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5973 }
5974
5977 constexpr bool has_subtype() const noexcept
5978 {
5979 return m_has_subtype;
5980 }
5981
5984 void clear_subtype() noexcept
5985 {
5986 m_subtype = 0;
5987 m_has_subtype = false;
5988 }
5989
5990 private:
5991 subtype_type m_subtype = 0;
5992 bool m_has_subtype = false;
5993};
5994
5996
5997// #include <nlohmann/detail/conversions/from_json.hpp>
5998
5999// #include <nlohmann/detail/conversions/to_json.hpp>
6000
6001// #include <nlohmann/detail/exceptions.hpp>
6002
6003// #include <nlohmann/detail/hash.hpp>
6004// __ _____ _____ _____
6005// __| | __| | | | JSON for Modern C++
6006// | | |__ | | | | | | version 3.11.3
6007// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6008//
6009// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6010// SPDX-License-Identifier: MIT
6011
6012
6013
6014#include <cstdint> // uint8_t
6015#include <cstddef> // size_t
6016#include <functional> // hash
6017
6018// #include <nlohmann/detail/abi_macros.hpp>
6019
6020// #include <nlohmann/detail/value_t.hpp>
6021
6022
6024namespace detail
6025{
6026
6027// boost::hash_combine
6028inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6029{
6030 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6031 return seed;
6032}
6033
6045template<typename BasicJsonType>
6046std::size_t hash(const BasicJsonType& j)
6047{
6048 using string_t = typename BasicJsonType::string_t;
6049 using number_integer_t = typename BasicJsonType::number_integer_t;
6050 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6051 using number_float_t = typename BasicJsonType::number_float_t;
6052
6053 const auto type = static_cast<std::size_t>(j.type());
6054 switch (j.type())
6055 {
6056 case BasicJsonType::value_t::null:
6057 case BasicJsonType::value_t::discarded:
6058 {
6059 return combine(type, 0);
6060 }
6061
6062 case BasicJsonType::value_t::object:
6063 {
6064 auto seed = combine(type, j.size());
6065 for (const auto& element : j.items())
6066 {
6067 const auto h = std::hash<string_t> {}(element.key());
6068 seed = combine(seed, h);
6069 seed = combine(seed, hash(element.value()));
6070 }
6071 return seed;
6072 }
6073
6074 case BasicJsonType::value_t::array:
6075 {
6076 auto seed = combine(type, j.size());
6077 for (const auto& element : j)
6078 {
6079 seed = combine(seed, hash(element));
6080 }
6081 return seed;
6082 }
6083
6084 case BasicJsonType::value_t::string:
6085 {
6086 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6087 return combine(type, h);
6088 }
6089
6090 case BasicJsonType::value_t::boolean:
6091 {
6092 const auto h = std::hash<bool> {}(j.template get<bool>());
6093 return combine(type, h);
6094 }
6095
6096 case BasicJsonType::value_t::number_integer:
6097 {
6098 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6099 return combine(type, h);
6100 }
6101
6102 case BasicJsonType::value_t::number_unsigned:
6103 {
6104 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6105 return combine(type, h);
6106 }
6107
6108 case BasicJsonType::value_t::number_float:
6109 {
6110 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6111 return combine(type, h);
6112 }
6113
6114 case BasicJsonType::value_t::binary:
6115 {
6116 auto seed = combine(type, j.get_binary().size());
6117 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6118 seed = combine(seed, h);
6119 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6120 for (const auto byte : j.get_binary())
6121 {
6122 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6123 }
6124 return seed;
6125 }
6126
6127 default: // LCOV_EXCL_LINE
6128 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6129 return 0; // LCOV_EXCL_LINE
6130 }
6131}
6132
6133} // namespace detail
6135
6136// #include <nlohmann/detail/input/binary_reader.hpp>
6137// __ _____ _____ _____
6138// __| | __| | | | JSON for Modern C++
6139// | | |__ | | | | | | version 3.11.3
6140// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6141//
6142// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6143// SPDX-License-Identifier: MIT
6144
6145
6146
6147#include <algorithm> // generate_n
6148#include <array> // array
6149#include <cmath> // ldexp
6150#include <cstddef> // size_t
6151#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6152#include <cstdio> // snprintf
6153#include <cstring> // memcpy
6154#include <iterator> // back_inserter
6155#include <limits> // numeric_limits
6156#include <string> // char_traits, string
6157#include <utility> // make_pair, move
6158#include <vector> // vector
6159
6160// #include <nlohmann/detail/exceptions.hpp>
6161
6162// #include <nlohmann/detail/input/input_adapters.hpp>
6163// __ _____ _____ _____
6164// __| | __| | | | JSON for Modern C++
6165// | | |__ | | | | | | version 3.11.3
6166// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6167//
6168// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6169// SPDX-License-Identifier: MIT
6170
6171
6172
6173#include <array> // array
6174#include <cstddef> // size_t
6175#include <cstring> // strlen
6176#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6177#include <memory> // shared_ptr, make_shared, addressof
6178#include <numeric> // accumulate
6179#include <string> // string, char_traits
6180#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6181#include <utility> // pair, declval
6182
6183#ifndef JSON_NO_IO
6184 #include <cstdio> // FILE *
6185 #include <istream> // istream
6186#endif // JSON_NO_IO
6187
6188// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6189
6190// #include <nlohmann/detail/macro_scope.hpp>
6191
6192// #include <nlohmann/detail/meta/type_traits.hpp>
6193
6194
6196namespace detail
6197{
6198
6201
6203// input adapters //
6205
6206#ifndef JSON_NO_IO
6212{
6213 public:
6214 using char_type = char;
6215
6217 explicit file_input_adapter(std::FILE* f) noexcept
6218 : m_file(f)
6219 {
6220 JSON_ASSERT(m_file != nullptr);
6221 }
6222
6223 // make class move-only
6226 file_input_adapter& operator=(const file_input_adapter&) = delete;
6229
6230 std::char_traits<char>::int_type get_character() noexcept
6231 {
6232 return std::fgetc(m_file);
6233 }
6234
6235 private:
6237 std::FILE* m_file;
6238};
6239
6250{
6251 public:
6252 using char_type = char;
6253
6255 {
6256 // clear stream flags; we use underlying streambuf I/O, do not
6257 // maintain ifstream flags, except eof
6258 if (is != nullptr)
6259 {
6260 is->clear(is->rdstate() & std::ios::eofbit);
6261 }
6262 }
6263
6264 explicit input_stream_adapter(std::istream& i)
6265 : is(&i), sb(i.rdbuf())
6266 {}
6267
6268 // delete because of pointer members
6272
6274 : is(rhs.is), sb(rhs.sb)
6275 {
6276 rhs.is = nullptr;
6277 rhs.sb = nullptr;
6278 }
6279
6280 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6281 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6282 // end up as the same value, e.g. 0xFFFFFFFF.
6283 std::char_traits<char>::int_type get_character()
6284 {
6285 auto res = sb->sbumpc();
6286 // set eof manually, as we don't use the istream interface.
6287 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6288 {
6289 is->clear(is->rdstate() | std::ios::eofbit);
6290 }
6291 return res;
6292 }
6293
6294 private:
6296 std::istream* is = nullptr;
6297 std::streambuf* sb = nullptr;
6298};
6299#endif // JSON_NO_IO
6300
6301// General-purpose iterator-based adapter. It might not be as fast as
6302// theoretically possible for some containers, but it is extremely versatile.
6303template<typename IteratorType>
6305{
6306 public:
6307 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6308
6309 iterator_input_adapter(IteratorType first, IteratorType last)
6310 : current(std::move(first)), end(std::move(last))
6311 {}
6312
6314 {
6315 if (JSON_HEDLEY_LIKELY(current != end))
6316 {
6317 auto result = char_traits<char_type>::to_int_type(*current);
6318 std::advance(current, 1);
6319 return result;
6320 }
6321
6323 }
6324
6325 private:
6326 IteratorType current;
6327 IteratorType end;
6328
6329 template<typename BaseInputAdapter, size_t T>
6331
6332 bool empty() const
6333 {
6334 return current == end;
6335 }
6336};
6337
6338template<typename BaseInputAdapter, size_t T>
6340
6341template<typename BaseInputAdapter>
6342struct wide_string_input_helper<BaseInputAdapter, 4>
6343{
6344 // UTF-32
6345 static void fill_buffer(BaseInputAdapter& input,
6346 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6347 size_t& utf8_bytes_index,
6348 size_t& utf8_bytes_filled)
6349 {
6350 utf8_bytes_index = 0;
6351
6352 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6353 {
6354 utf8_bytes[0] = std::char_traits<char>::eof();
6355 utf8_bytes_filled = 1;
6356 }
6357 else
6358 {
6359 // get the current character
6360 const auto wc = input.get_character();
6361
6362 // UTF-32 to UTF-8 encoding
6363 if (wc < 0x80)
6364 {
6365 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6366 utf8_bytes_filled = 1;
6367 }
6368 else if (wc <= 0x7FF)
6369 {
6370 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6371 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6372 utf8_bytes_filled = 2;
6373 }
6374 else if (wc <= 0xFFFF)
6375 {
6376 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6377 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6378 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6379 utf8_bytes_filled = 3;
6380 }
6381 else if (wc <= 0x10FFFF)
6382 {
6383 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6384 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6385 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6386 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6387 utf8_bytes_filled = 4;
6388 }
6389 else
6390 {
6391 // unknown character
6392 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6393 utf8_bytes_filled = 1;
6394 }
6395 }
6396 }
6397};
6398
6399template<typename BaseInputAdapter>
6400struct wide_string_input_helper<BaseInputAdapter, 2>
6401{
6402 // UTF-16
6403 static void fill_buffer(BaseInputAdapter& input,
6404 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6405 size_t& utf8_bytes_index,
6406 size_t& utf8_bytes_filled)
6407 {
6408 utf8_bytes_index = 0;
6409
6410 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6411 {
6412 utf8_bytes[0] = std::char_traits<char>::eof();
6413 utf8_bytes_filled = 1;
6414 }
6415 else
6416 {
6417 // get the current character
6418 const auto wc = input.get_character();
6419
6420 // UTF-16 to UTF-8 encoding
6421 if (wc < 0x80)
6422 {
6423 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6424 utf8_bytes_filled = 1;
6425 }
6426 else if (wc <= 0x7FF)
6427 {
6428 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6429 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6430 utf8_bytes_filled = 2;
6431 }
6432 else if (0xD800 > wc || wc >= 0xE000)
6433 {
6434 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6435 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6436 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6437 utf8_bytes_filled = 3;
6438 }
6439 else
6440 {
6441 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6442 {
6443 const auto wc2 = static_cast<unsigned int>(input.get_character());
6444 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6445 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6446 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6447 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6448 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6449 utf8_bytes_filled = 4;
6450 }
6451 else
6452 {
6453 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6454 utf8_bytes_filled = 1;
6455 }
6456 }
6457 }
6458 }
6459};
6460
6461// Wraps another input adapter to convert wide character types into individual bytes.
6462template<typename BaseInputAdapter, typename WideCharType>
6464{
6465 public:
6466 using char_type = char;
6467
6468 wide_string_input_adapter(BaseInputAdapter base)
6469 : base_adapter(base) {}
6470
6471 typename std::char_traits<char>::int_type get_character() noexcept
6472 {
6473 // check if buffer needs to be filled
6474 if (utf8_bytes_index == utf8_bytes_filled)
6475 {
6476 fill_buffer<sizeof(WideCharType)>();
6477
6478 JSON_ASSERT(utf8_bytes_filled > 0);
6479 JSON_ASSERT(utf8_bytes_index == 0);
6480 }
6481
6482 // use buffer
6483 JSON_ASSERT(utf8_bytes_filled > 0);
6484 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6485 return utf8_bytes[utf8_bytes_index++];
6486 }
6487
6488 private:
6489 BaseInputAdapter base_adapter;
6490
6491 template<size_t T>
6492 void fill_buffer()
6493 {
6494 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6495 }
6496
6498 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6499
6501 std::size_t utf8_bytes_index = 0;
6503 std::size_t utf8_bytes_filled = 0;
6504};
6505
6506template<typename IteratorType, typename Enable = void>
6508{
6509 using iterator_type = IteratorType;
6510 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6512
6513 static adapter_type create(IteratorType first, IteratorType last)
6514 {
6515 return adapter_type(std::move(first), std::move(last));
6516 }
6517};
6518
6519template<typename T>
6521{
6522 using value_type = typename std::iterator_traits<T>::value_type;
6523 enum
6524 {
6525 value = sizeof(value_type) > 1
6526 };
6527};
6528
6529template<typename IteratorType>
6531{
6532 using iterator_type = IteratorType;
6533 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6536
6537 static adapter_type create(IteratorType first, IteratorType last)
6538 {
6539 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6540 }
6541};
6542
6543// General purpose iterator-based input
6544template<typename IteratorType>
6546{
6548 return factory_type::create(first, last);
6549}
6550
6551// Convenience shorthand from container to iterator
6552// Enables ADL on begin(container) and end(container)
6553// Encloses the using declarations in namespace for not to leak them to outside scope
6554
6555namespace container_input_adapter_factory_impl
6556{
6557
6558using std::begin;
6559using std::end;
6560
6561template<typename ContainerType, typename Enable = void>
6563
6564template<typename ContainerType>
6566 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6567 {
6568 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6569
6570 static adapter_type create(const ContainerType& container)
6571{
6572 return input_adapter(begin(container), end(container));
6573}
6574 };
6575
6576} // namespace container_input_adapter_factory_impl
6577
6578template<typename ContainerType>
6583
6584#ifndef JSON_NO_IO
6585// Special cases with fast paths
6586inline file_input_adapter input_adapter(std::FILE* file)
6587{
6588 return file_input_adapter(file);
6589}
6590
6591inline input_stream_adapter input_adapter(std::istream& stream)
6592{
6593 return input_stream_adapter(stream);
6594}
6595
6596inline input_stream_adapter input_adapter(std::istream&& stream)
6597{
6598 return input_stream_adapter(stream);
6599}
6600#endif // JSON_NO_IO
6601
6602using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6603
6604// Null-delimited strings, and the like.
6605template < typename CharT,
6606 typename std::enable_if <
6607 std::is_pointer<CharT>::value&&
6608 !std::is_array<CharT>::value&&
6609 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6610 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6611 int >::type = 0 >
6613{
6614 auto length = std::strlen(reinterpret_cast<const char*>(b));
6615 const auto* ptr = reinterpret_cast<const char*>(b);
6616 return input_adapter(ptr, ptr + length);
6617}
6618
6619template<typename T, std::size_t N>
6620auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6621{
6622 return input_adapter(array, array + N);
6623}
6624
6625// This class only handles inputs of input_buffer_adapter type.
6626// It's required so that expressions like {ptr, len} can be implicitly cast
6627// to the correct adapter.
6629{
6630 public:
6631 template < typename CharT,
6632 typename std::enable_if <
6633 std::is_pointer<CharT>::value&&
6634 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6635 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6636 int >::type = 0 >
6637 span_input_adapter(CharT b, std::size_t l)
6638 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6639
6640 template<class IteratorType,
6641 typename std::enable_if<
6642 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6643 int>::type = 0>
6644 span_input_adapter(IteratorType first, IteratorType last)
6645 : ia(input_adapter(first, last)) {}
6646
6648 {
6649 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6650 }
6651
6652 private:
6654};
6655
6656} // namespace detail
6658
6659// #include <nlohmann/detail/input/json_sax.hpp>
6660// __ _____ _____ _____
6661// __| | __| | | | JSON for Modern C++
6662// | | |__ | | | | | | version 3.11.3
6663// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6664//
6665// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6666// SPDX-License-Identifier: MIT
6667
6668
6669
6670#include <cstddef>
6671#include <string> // string
6672#include <utility> // move
6673#include <vector> // vector
6674
6675// #include <nlohmann/detail/exceptions.hpp>
6676
6677// #include <nlohmann/detail/macro_scope.hpp>
6678
6679// #include <nlohmann/detail/string_concat.hpp>
6680
6681
6683
6692template<typename BasicJsonType>
6694{
6695 using number_integer_t = typename BasicJsonType::number_integer_t;
6696 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6697 using number_float_t = typename BasicJsonType::number_float_t;
6698 using string_t = typename BasicJsonType::string_t;
6699 using binary_t = typename BasicJsonType::binary_t;
6700
6705 virtual bool null() = 0;
6706
6712 virtual bool boolean(bool val) = 0;
6713
6719 virtual bool number_integer(number_integer_t val) = 0;
6720
6726 virtual bool number_unsigned(number_unsigned_t val) = 0;
6727
6734 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6735
6742 virtual bool string(string_t& val) = 0;
6743
6750 virtual bool binary(binary_t& val) = 0;
6751
6758 virtual bool start_object(std::size_t elements) = 0;
6759
6766 virtual bool key(string_t& val) = 0;
6767
6772 virtual bool end_object() = 0;
6773
6780 virtual bool start_array(std::size_t elements) = 0;
6781
6786 virtual bool end_array() = 0;
6787
6795 virtual bool parse_error(std::size_t position,
6796 const std::string& last_token,
6797 const detail::exception& ex) = 0;
6798
6799 json_sax() = default;
6800 json_sax(const json_sax&) = default;
6801 json_sax(json_sax&&) noexcept = default;
6802 json_sax& operator=(const json_sax&) = default;
6803 json_sax& operator=(json_sax&&) noexcept = default;
6804 virtual ~json_sax() = default;
6805};
6806
6807namespace detail
6808{
6822template<typename BasicJsonType>
6824{
6825 public:
6826 using number_integer_t = typename BasicJsonType::number_integer_t;
6827 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6828 using number_float_t = typename BasicJsonType::number_float_t;
6829 using string_t = typename BasicJsonType::string_t;
6830 using binary_t = typename BasicJsonType::binary_t;
6831
6837 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6838 : root(r), allow_exceptions(allow_exceptions_)
6839 {}
6840
6841 // make class move-only
6843 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6845 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6847
6848 bool null()
6849 {
6850 handle_value(nullptr);
6851 return true;
6852 }
6853
6854 bool boolean(bool val)
6855 {
6856 handle_value(val);
6857 return true;
6858 }
6859
6861 {
6862 handle_value(val);
6863 return true;
6864 }
6865
6867 {
6868 handle_value(val);
6869 return true;
6870 }
6871
6872 bool number_float(number_float_t val, const string_t& /*unused*/)
6873 {
6874 handle_value(val);
6875 return true;
6876 }
6877
6878 bool string(string_t& val)
6879 {
6880 handle_value(val);
6881 return true;
6882 }
6883
6884 bool binary(binary_t& val)
6885 {
6886 handle_value(std::move(val));
6887 return true;
6888 }
6889
6890 bool start_object(std::size_t len)
6891 {
6892 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6893
6894 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6895 {
6896 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6897 }
6898
6899 return true;
6900 }
6901
6902 bool key(string_t& val)
6903 {
6904 JSON_ASSERT(!ref_stack.empty());
6905 JSON_ASSERT(ref_stack.back()->is_object());
6906
6907 // add null at given key and store the reference for later
6908 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6909 return true;
6910 }
6911
6913 {
6914 JSON_ASSERT(!ref_stack.empty());
6915 JSON_ASSERT(ref_stack.back()->is_object());
6916
6917 ref_stack.back()->set_parents();
6918 ref_stack.pop_back();
6919 return true;
6920 }
6921
6922 bool start_array(std::size_t len)
6923 {
6924 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6925
6926 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6927 {
6928 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6929 }
6930
6931 return true;
6932 }
6933
6935 {
6936 JSON_ASSERT(!ref_stack.empty());
6937 JSON_ASSERT(ref_stack.back()->is_array());
6938
6939 ref_stack.back()->set_parents();
6940 ref_stack.pop_back();
6941 return true;
6942 }
6943
6944 template<class Exception>
6945 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6946 const Exception& ex)
6947 {
6948 errored = true;
6949 static_cast<void>(ex);
6950 if (allow_exceptions)
6951 {
6952 JSON_THROW(ex);
6953 }
6954 return false;
6955 }
6956
6957 constexpr bool is_errored() const
6958 {
6959 return errored;
6960 }
6961
6962 private:
6969 template<typename Value>
6971 BasicJsonType* handle_value(Value&& v)
6972 {
6973 if (ref_stack.empty())
6974 {
6975 root = BasicJsonType(std::forward<Value>(v));
6976 return &root;
6977 }
6978
6979 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6980
6981 if (ref_stack.back()->is_array())
6982 {
6983 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6984 return &(ref_stack.back()->m_data.m_value.array->back());
6985 }
6986
6987 JSON_ASSERT(ref_stack.back()->is_object());
6988 JSON_ASSERT(object_element);
6989 *object_element = BasicJsonType(std::forward<Value>(v));
6990 return object_element;
6991 }
6992
6994 BasicJsonType& root;
6996 std::vector<BasicJsonType*> ref_stack {};
6998 BasicJsonType* object_element = nullptr;
7000 bool errored = false;
7002 const bool allow_exceptions = true;
7003};
7004
7005template<typename BasicJsonType>
7007{
7008 public:
7009 using number_integer_t = typename BasicJsonType::number_integer_t;
7010 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7011 using number_float_t = typename BasicJsonType::number_float_t;
7012 using string_t = typename BasicJsonType::string_t;
7013 using binary_t = typename BasicJsonType::binary_t;
7014 using parser_callback_t = typename BasicJsonType::parser_callback_t;
7015 using parse_event_t = typename BasicJsonType::parse_event_t;
7016
7018 const parser_callback_t cb,
7019 const bool allow_exceptions_ = true)
7020 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
7021 {
7022 keep_stack.push_back(true);
7023 }
7024
7025 // make class move-only
7027 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7029 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7031
7032 bool null()
7033 {
7034 handle_value(nullptr);
7035 return true;
7036 }
7037
7038 bool boolean(bool val)
7039 {
7040 handle_value(val);
7041 return true;
7042 }
7043
7045 {
7046 handle_value(val);
7047 return true;
7048 }
7049
7051 {
7052 handle_value(val);
7053 return true;
7054 }
7055
7056 bool number_float(number_float_t val, const string_t& /*unused*/)
7057 {
7058 handle_value(val);
7059 return true;
7060 }
7061
7062 bool string(string_t& val)
7063 {
7064 handle_value(val);
7065 return true;
7066 }
7067
7068 bool binary(binary_t& val)
7069 {
7070 handle_value(std::move(val));
7071 return true;
7072 }
7073
7074 bool start_object(std::size_t len)
7075 {
7076 // check callback for object start
7077 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7078 keep_stack.push_back(keep);
7079
7080 auto val = handle_value(BasicJsonType::value_t::object, true);
7081 ref_stack.push_back(val.second);
7082
7083 // check object limit
7084 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7085 {
7086 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7087 }
7088
7089 return true;
7090 }
7091
7092 bool key(string_t& val)
7093 {
7094 BasicJsonType k = BasicJsonType(val);
7095
7096 // check callback for key
7097 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7098 key_keep_stack.push_back(keep);
7099
7100 // add discarded value at given key and store the reference for later
7101 if (keep && ref_stack.back())
7102 {
7103 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7104 }
7105
7106 return true;
7107 }
7108
7110 {
7111 if (ref_stack.back())
7112 {
7113 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7114 {
7115 // discard object
7116 *ref_stack.back() = discarded;
7117 }
7118 else
7119 {
7120 ref_stack.back()->set_parents();
7121 }
7122 }
7123
7124 JSON_ASSERT(!ref_stack.empty());
7125 JSON_ASSERT(!keep_stack.empty());
7126 ref_stack.pop_back();
7127 keep_stack.pop_back();
7128
7129 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7130 {
7131 // remove discarded value
7132 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7133 {
7134 if (it->is_discarded())
7135 {
7136 ref_stack.back()->erase(it);
7137 break;
7138 }
7139 }
7140 }
7141
7142 return true;
7143 }
7144
7145 bool start_array(std::size_t len)
7146 {
7147 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7148 keep_stack.push_back(keep);
7149
7150 auto val = handle_value(BasicJsonType::value_t::array, true);
7151 ref_stack.push_back(val.second);
7152
7153 // check array limit
7154 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7155 {
7156 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7157 }
7158
7159 return true;
7160 }
7161
7163 {
7164 bool keep = true;
7165
7166 if (ref_stack.back())
7167 {
7168 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7169 if (keep)
7170 {
7171 ref_stack.back()->set_parents();
7172 }
7173 else
7174 {
7175 // discard array
7176 *ref_stack.back() = discarded;
7177 }
7178 }
7179
7180 JSON_ASSERT(!ref_stack.empty());
7181 JSON_ASSERT(!keep_stack.empty());
7182 ref_stack.pop_back();
7183 keep_stack.pop_back();
7184
7185 // remove discarded value
7186 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7187 {
7188 ref_stack.back()->m_data.m_value.array->pop_back();
7189 }
7190
7191 return true;
7192 }
7193
7194 template<class Exception>
7195 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7196 const Exception& ex)
7197 {
7198 errored = true;
7199 static_cast<void>(ex);
7200 if (allow_exceptions)
7201 {
7202 JSON_THROW(ex);
7203 }
7204 return false;
7205 }
7206
7207 constexpr bool is_errored() const
7208 {
7209 return errored;
7210 }
7211
7212 private:
7228 template<typename Value>
7229 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7230 {
7231 JSON_ASSERT(!keep_stack.empty());
7232
7233 // do not handle this value if we know it would be added to a discarded
7234 // container
7235 if (!keep_stack.back())
7236 {
7237 return {false, nullptr};
7238 }
7239
7240 // create value
7241 auto value = BasicJsonType(std::forward<Value>(v));
7242
7243 // check callback
7244 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7245
7246 // do not handle this value if we just learnt it shall be discarded
7247 if (!keep)
7248 {
7249 return {false, nullptr};
7250 }
7251
7252 if (ref_stack.empty())
7253 {
7254 root = std::move(value);
7255 return {true, & root};
7256 }
7257
7258 // skip this value if we already decided to skip the parent
7259 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7260 if (!ref_stack.back())
7261 {
7262 return {false, nullptr};
7263 }
7264
7265 // we now only expect arrays and objects
7266 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7267
7268 // array
7269 if (ref_stack.back()->is_array())
7270 {
7271 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7272 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7273 }
7274
7275 // object
7276 JSON_ASSERT(ref_stack.back()->is_object());
7277 // check if we should store an element for the current key
7278 JSON_ASSERT(!key_keep_stack.empty());
7279 const bool store_element = key_keep_stack.back();
7280 key_keep_stack.pop_back();
7281
7282 if (!store_element)
7283 {
7284 return {false, nullptr};
7285 }
7286
7287 JSON_ASSERT(object_element);
7288 *object_element = std::move(value);
7289 return {true, object_element};
7290 }
7291
7293 BasicJsonType& root;
7295 std::vector<BasicJsonType*> ref_stack {};
7297 std::vector<bool> keep_stack {};
7299 std::vector<bool> key_keep_stack {};
7301 BasicJsonType* object_element = nullptr;
7303 bool errored = false;
7305 const parser_callback_t callback = nullptr;
7307 const bool allow_exceptions = true;
7309 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7310};
7311
7312template<typename BasicJsonType>
7314{
7315 public:
7316 using number_integer_t = typename BasicJsonType::number_integer_t;
7317 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7318 using number_float_t = typename BasicJsonType::number_float_t;
7319 using string_t = typename BasicJsonType::string_t;
7320 using binary_t = typename BasicJsonType::binary_t;
7321
7322 bool null()
7323 {
7324 return true;
7325 }
7326
7327 bool boolean(bool /*unused*/)
7328 {
7329 return true;
7330 }
7331
7333 {
7334 return true;
7335 }
7336
7338 {
7339 return true;
7340 }
7341
7342 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7343 {
7344 return true;
7345 }
7346
7347 bool string(string_t& /*unused*/)
7348 {
7349 return true;
7350 }
7351
7352 bool binary(binary_t& /*unused*/)
7353 {
7354 return true;
7355 }
7356
7357 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7358 {
7359 return true;
7360 }
7361
7362 bool key(string_t& /*unused*/)
7363 {
7364 return true;
7365 }
7366
7368 {
7369 return true;
7370 }
7371
7372 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7373 {
7374 return true;
7375 }
7376
7378 {
7379 return true;
7380 }
7381
7382 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7383 {
7384 return false;
7385 }
7386};
7387
7388} // namespace detail
7390
7391// #include <nlohmann/detail/input/lexer.hpp>
7392// __ _____ _____ _____
7393// __| | __| | | | JSON for Modern C++
7394// | | |__ | | | | | | version 3.11.3
7395// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7396//
7397// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7398// SPDX-License-Identifier: MIT
7399
7400
7401
7402#include <array> // array
7403#include <clocale> // localeconv
7404#include <cstddef> // size_t
7405#include <cstdio> // snprintf
7406#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7407#include <initializer_list> // initializer_list
7408#include <string> // char_traits, string
7409#include <utility> // move
7410#include <vector> // vector
7411
7412// #include <nlohmann/detail/input/input_adapters.hpp>
7413
7414// #include <nlohmann/detail/input/position_t.hpp>
7415
7416// #include <nlohmann/detail/macro_scope.hpp>
7417
7418// #include <nlohmann/detail/meta/type_traits.hpp>
7419
7420
7422namespace detail
7423{
7424
7426// lexer //
7428
7429template<typename BasicJsonType>
7431{
7432 public:
7434 enum class token_type
7435 {
7436 uninitialized,
7437 literal_true,
7438 literal_false,
7439 literal_null,
7440 value_string,
7441 value_unsigned,
7442 value_integer,
7443 value_float,
7444 begin_array,
7445 begin_object,
7446 end_array,
7447 end_object,
7448 name_separator,
7449 value_separator,
7450 parse_error,
7451 end_of_input,
7452 literal_or_value
7453 };
7454
7458 static const char* token_type_name(const token_type t) noexcept
7459 {
7460 switch (t)
7461 {
7462 case token_type::uninitialized:
7463 return "<uninitialized>";
7464 case token_type::literal_true:
7465 return "true literal";
7466 case token_type::literal_false:
7467 return "false literal";
7468 case token_type::literal_null:
7469 return "null literal";
7470 case token_type::value_string:
7471 return "string literal";
7472 case token_type::value_unsigned:
7473 case token_type::value_integer:
7474 case token_type::value_float:
7475 return "number literal";
7476 case token_type::begin_array:
7477 return "'['";
7478 case token_type::begin_object:
7479 return "'{'";
7480 case token_type::end_array:
7481 return "']'";
7482 case token_type::end_object:
7483 return "'}'";
7484 case token_type::name_separator:
7485 return "':'";
7486 case token_type::value_separator:
7487 return "','";
7488 case token_type::parse_error:
7489 return "<parse error>";
7490 case token_type::end_of_input:
7491 return "end of input";
7492 case token_type::literal_or_value:
7493 return "'[', '{', or a literal";
7494 // LCOV_EXCL_START
7495 default: // catch non-enum values
7496 return "unknown token";
7497 // LCOV_EXCL_STOP
7498 }
7499 }
7500};
7506template<typename BasicJsonType, typename InputAdapterType>
7507class lexer : public lexer_base<BasicJsonType>
7508{
7509 using number_integer_t = typename BasicJsonType::number_integer_t;
7510 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7511 using number_float_t = typename BasicJsonType::number_float_t;
7512 using string_t = typename BasicJsonType::string_t;
7513 using char_type = typename InputAdapterType::char_type;
7514 using char_int_type = typename char_traits<char_type>::int_type;
7515
7516 public:
7518
7519 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7520 : ia(std::move(adapter))
7521 , ignore_comments(ignore_comments_)
7522 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7523 {}
7524
7525 // delete because of pointer members
7526 lexer(const lexer&) = delete;
7527 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7528 lexer& operator=(lexer&) = delete;
7529 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7530 ~lexer() = default;
7531
7532 private:
7534 // locales
7536
7539 static char get_decimal_point() noexcept
7540 {
7541 const auto* loc = localeconv();
7542 JSON_ASSERT(loc != nullptr);
7543 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7544 }
7545
7547 // scan functions
7549
7565 int get_codepoint()
7566 {
7567 // this function only makes sense after reading `\u`
7568 JSON_ASSERT(current == 'u');
7569 int codepoint = 0;
7570
7571 const auto factors = { 12u, 8u, 4u, 0u };
7572 for (const auto factor : factors)
7573 {
7574 get();
7575
7576 if (current >= '0' && current <= '9')
7577 {
7578 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7579 }
7580 else if (current >= 'A' && current <= 'F')
7581 {
7582 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7583 }
7584 else if (current >= 'a' && current <= 'f')
7585 {
7586 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7587 }
7588 else
7589 {
7590 return -1;
7591 }
7592 }
7593
7594 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7595 return codepoint;
7596 }
7597
7613 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7614 {
7615 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7616 add(current);
7617
7618 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7619 {
7620 get();
7621 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7622 {
7623 add(current);
7624 }
7625 else
7626 {
7627 error_message = "invalid string: ill-formed UTF-8 byte";
7628 return false;
7629 }
7630 }
7631
7632 return true;
7633 }
7634
7650 token_type scan_string()
7651 {
7652 // reset token_buffer (ignore opening quote)
7653 reset();
7654
7655 // we entered the function by reading an open quote
7656 JSON_ASSERT(current == '\"');
7657
7658 while (true)
7659 {
7660 // get next character
7661 switch (get())
7662 {
7663 // end of file while parsing string
7664 case char_traits<char_type>::eof():
7665 {
7666 error_message = "invalid string: missing closing quote";
7667 return token_type::parse_error;
7668 }
7669
7670 // closing quote
7671 case '\"':
7672 {
7673 return token_type::value_string;
7674 }
7675
7676 // escapes
7677 case '\\':
7678 {
7679 switch (get())
7680 {
7681 // quotation mark
7682 case '\"':
7683 add('\"');
7684 break;
7685 // reverse solidus
7686 case '\\':
7687 add('\\');
7688 break;
7689 // solidus
7690 case '/':
7691 add('/');
7692 break;
7693 // backspace
7694 case 'b':
7695 add('\b');
7696 break;
7697 // form feed
7698 case 'f':
7699 add('\f');
7700 break;
7701 // line feed
7702 case 'n':
7703 add('\n');
7704 break;
7705 // carriage return
7706 case 'r':
7707 add('\r');
7708 break;
7709 // tab
7710 case 't':
7711 add('\t');
7712 break;
7713
7714 // unicode escapes
7715 case 'u':
7716 {
7717 const int codepoint1 = get_codepoint();
7718 int codepoint = codepoint1; // start with codepoint1
7719
7720 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7721 {
7722 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7723 return token_type::parse_error;
7724 }
7725
7726 // check if code point is a high surrogate
7727 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7728 {
7729 // expect next \uxxxx entry
7730 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7731 {
7732 const int codepoint2 = get_codepoint();
7733
7734 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7735 {
7736 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7737 return token_type::parse_error;
7738 }
7739
7740 // check if codepoint2 is a low surrogate
7741 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7742 {
7743 // overwrite codepoint
7744 codepoint = static_cast<int>(
7745 // high surrogate occupies the most significant 22 bits
7746 (static_cast<unsigned int>(codepoint1) << 10u)
7747 // low surrogate occupies the least significant 15 bits
7748 + static_cast<unsigned int>(codepoint2)
7749 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7750 // in the result, so we have to subtract with:
7751 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7752 - 0x35FDC00u);
7753 }
7754 else
7755 {
7756 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7757 return token_type::parse_error;
7758 }
7759 }
7760 else
7761 {
7762 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7763 return token_type::parse_error;
7764 }
7765 }
7766 else
7767 {
7768 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7769 {
7770 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7771 return token_type::parse_error;
7772 }
7773 }
7774
7775 // result of the above calculation yields a proper codepoint
7776 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7777
7778 // translate codepoint into bytes
7779 if (codepoint < 0x80)
7780 {
7781 // 1-byte characters: 0xxxxxxx (ASCII)
7782 add(static_cast<char_int_type>(codepoint));
7783 }
7784 else if (codepoint <= 0x7FF)
7785 {
7786 // 2-byte characters: 110xxxxx 10xxxxxx
7787 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7788 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7789 }
7790 else if (codepoint <= 0xFFFF)
7791 {
7792 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7793 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7794 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7795 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7796 }
7797 else
7798 {
7799 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7800 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7801 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7802 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7803 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7804 }
7805
7806 break;
7807 }
7808
7809 // other characters after escape
7810 default:
7811 error_message = "invalid string: forbidden character after backslash";
7812 return token_type::parse_error;
7813 }
7814
7815 break;
7816 }
7817
7818 // invalid control characters
7819 case 0x00:
7820 {
7821 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7822 return token_type::parse_error;
7823 }
7824
7825 case 0x01:
7826 {
7827 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7828 return token_type::parse_error;
7829 }
7830
7831 case 0x02:
7832 {
7833 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7834 return token_type::parse_error;
7835 }
7836
7837 case 0x03:
7838 {
7839 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7840 return token_type::parse_error;
7841 }
7842
7843 case 0x04:
7844 {
7845 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7846 return token_type::parse_error;
7847 }
7848
7849 case 0x05:
7850 {
7851 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7852 return token_type::parse_error;
7853 }
7854
7855 case 0x06:
7856 {
7857 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7858 return token_type::parse_error;
7859 }
7860
7861 case 0x07:
7862 {
7863 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7864 return token_type::parse_error;
7865 }
7866
7867 case 0x08:
7868 {
7869 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7870 return token_type::parse_error;
7871 }
7872
7873 case 0x09:
7874 {
7875 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7876 return token_type::parse_error;
7877 }
7878
7879 case 0x0A:
7880 {
7881 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7882 return token_type::parse_error;
7883 }
7884
7885 case 0x0B:
7886 {
7887 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7888 return token_type::parse_error;
7889 }
7890
7891 case 0x0C:
7892 {
7893 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7894 return token_type::parse_error;
7895 }
7896
7897 case 0x0D:
7898 {
7899 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7900 return token_type::parse_error;
7901 }
7902
7903 case 0x0E:
7904 {
7905 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7906 return token_type::parse_error;
7907 }
7908
7909 case 0x0F:
7910 {
7911 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7912 return token_type::parse_error;
7913 }
7914
7915 case 0x10:
7916 {
7917 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7918 return token_type::parse_error;
7919 }
7920
7921 case 0x11:
7922 {
7923 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7924 return token_type::parse_error;
7925 }
7926
7927 case 0x12:
7928 {
7929 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7930 return token_type::parse_error;
7931 }
7932
7933 case 0x13:
7934 {
7935 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7936 return token_type::parse_error;
7937 }
7938
7939 case 0x14:
7940 {
7941 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7942 return token_type::parse_error;
7943 }
7944
7945 case 0x15:
7946 {
7947 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7948 return token_type::parse_error;
7949 }
7950
7951 case 0x16:
7952 {
7953 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7954 return token_type::parse_error;
7955 }
7956
7957 case 0x17:
7958 {
7959 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7960 return token_type::parse_error;
7961 }
7962
7963 case 0x18:
7964 {
7965 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7966 return token_type::parse_error;
7967 }
7968
7969 case 0x19:
7970 {
7971 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7972 return token_type::parse_error;
7973 }
7974
7975 case 0x1A:
7976 {
7977 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7978 return token_type::parse_error;
7979 }
7980
7981 case 0x1B:
7982 {
7983 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7984 return token_type::parse_error;
7985 }
7986
7987 case 0x1C:
7988 {
7989 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7990 return token_type::parse_error;
7991 }
7992
7993 case 0x1D:
7994 {
7995 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7996 return token_type::parse_error;
7997 }
7998
7999 case 0x1E:
8000 {
8001 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
8002 return token_type::parse_error;
8003 }
8004
8005 case 0x1F:
8006 {
8007 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
8008 return token_type::parse_error;
8009 }
8010
8011 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8012 case 0x20:
8013 case 0x21:
8014 case 0x23:
8015 case 0x24:
8016 case 0x25:
8017 case 0x26:
8018 case 0x27:
8019 case 0x28:
8020 case 0x29:
8021 case 0x2A:
8022 case 0x2B:
8023 case 0x2C:
8024 case 0x2D:
8025 case 0x2E:
8026 case 0x2F:
8027 case 0x30:
8028 case 0x31:
8029 case 0x32:
8030 case 0x33:
8031 case 0x34:
8032 case 0x35:
8033 case 0x36:
8034 case 0x37:
8035 case 0x38:
8036 case 0x39:
8037 case 0x3A:
8038 case 0x3B:
8039 case 0x3C:
8040 case 0x3D:
8041 case 0x3E:
8042 case 0x3F:
8043 case 0x40:
8044 case 0x41:
8045 case 0x42:
8046 case 0x43:
8047 case 0x44:
8048 case 0x45:
8049 case 0x46:
8050 case 0x47:
8051 case 0x48:
8052 case 0x49:
8053 case 0x4A:
8054 case 0x4B:
8055 case 0x4C:
8056 case 0x4D:
8057 case 0x4E:
8058 case 0x4F:
8059 case 0x50:
8060 case 0x51:
8061 case 0x52:
8062 case 0x53:
8063 case 0x54:
8064 case 0x55:
8065 case 0x56:
8066 case 0x57:
8067 case 0x58:
8068 case 0x59:
8069 case 0x5A:
8070 case 0x5B:
8071 case 0x5D:
8072 case 0x5E:
8073 case 0x5F:
8074 case 0x60:
8075 case 0x61:
8076 case 0x62:
8077 case 0x63:
8078 case 0x64:
8079 case 0x65:
8080 case 0x66:
8081 case 0x67:
8082 case 0x68:
8083 case 0x69:
8084 case 0x6A:
8085 case 0x6B:
8086 case 0x6C:
8087 case 0x6D:
8088 case 0x6E:
8089 case 0x6F:
8090 case 0x70:
8091 case 0x71:
8092 case 0x72:
8093 case 0x73:
8094 case 0x74:
8095 case 0x75:
8096 case 0x76:
8097 case 0x77:
8098 case 0x78:
8099 case 0x79:
8100 case 0x7A:
8101 case 0x7B:
8102 case 0x7C:
8103 case 0x7D:
8104 case 0x7E:
8105 case 0x7F:
8106 {
8107 add(current);
8108 break;
8109 }
8110
8111 // U+0080..U+07FF: bytes C2..DF 80..BF
8112 case 0xC2:
8113 case 0xC3:
8114 case 0xC4:
8115 case 0xC5:
8116 case 0xC6:
8117 case 0xC7:
8118 case 0xC8:
8119 case 0xC9:
8120 case 0xCA:
8121 case 0xCB:
8122 case 0xCC:
8123 case 0xCD:
8124 case 0xCE:
8125 case 0xCF:
8126 case 0xD0:
8127 case 0xD1:
8128 case 0xD2:
8129 case 0xD3:
8130 case 0xD4:
8131 case 0xD5:
8132 case 0xD6:
8133 case 0xD7:
8134 case 0xD8:
8135 case 0xD9:
8136 case 0xDA:
8137 case 0xDB:
8138 case 0xDC:
8139 case 0xDD:
8140 case 0xDE:
8141 case 0xDF:
8142 {
8143 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8144 {
8145 return token_type::parse_error;
8146 }
8147 break;
8148 }
8149
8150 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8151 case 0xE0:
8152 {
8153 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8154 {
8155 return token_type::parse_error;
8156 }
8157 break;
8158 }
8159
8160 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8161 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8162 case 0xE1:
8163 case 0xE2:
8164 case 0xE3:
8165 case 0xE4:
8166 case 0xE5:
8167 case 0xE6:
8168 case 0xE7:
8169 case 0xE8:
8170 case 0xE9:
8171 case 0xEA:
8172 case 0xEB:
8173 case 0xEC:
8174 case 0xEE:
8175 case 0xEF:
8176 {
8177 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8178 {
8179 return token_type::parse_error;
8180 }
8181 break;
8182 }
8183
8184 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8185 case 0xED:
8186 {
8187 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8188 {
8189 return token_type::parse_error;
8190 }
8191 break;
8192 }
8193
8194 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8195 case 0xF0:
8196 {
8197 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8198 {
8199 return token_type::parse_error;
8200 }
8201 break;
8202 }
8203
8204 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8205 case 0xF1:
8206 case 0xF2:
8207 case 0xF3:
8208 {
8209 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8210 {
8211 return token_type::parse_error;
8212 }
8213 break;
8214 }
8215
8216 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8217 case 0xF4:
8218 {
8219 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8220 {
8221 return token_type::parse_error;
8222 }
8223 break;
8224 }
8225
8226 // remaining bytes (80..C1 and F5..FF) are ill-formed
8227 default:
8228 {
8229 error_message = "invalid string: ill-formed UTF-8 byte";
8230 return token_type::parse_error;
8231 }
8232 }
8233 }
8234 }
8235
8240 bool scan_comment()
8241 {
8242 switch (get())
8243 {
8244 // single-line comments skip input until a newline or EOF is read
8245 case '/':
8246 {
8247 while (true)
8248 {
8249 switch (get())
8250 {
8251 case '\n':
8252 case '\r':
8253 case char_traits<char_type>::eof():
8254 case '\0':
8255 return true;
8256
8257 default:
8258 break;
8259 }
8260 }
8261 }
8262
8263 // multi-line comments skip input until */ is read
8264 case '*':
8265 {
8266 while (true)
8267 {
8268 switch (get())
8269 {
8270 case char_traits<char_type>::eof():
8271 case '\0':
8272 {
8273 error_message = "invalid comment; missing closing '*/'";
8274 return false;
8275 }
8276
8277 case '*':
8278 {
8279 switch (get())
8280 {
8281 case '/':
8282 return true;
8283
8284 default:
8285 {
8286 unget();
8287 continue;
8288 }
8289 }
8290 }
8291
8292 default:
8293 continue;
8294 }
8295 }
8296 }
8297
8298 // unexpected character after reading '/'
8299 default:
8300 {
8301 error_message = "invalid comment; expecting '/' or '*' after '/'";
8302 return false;
8303 }
8304 }
8305 }
8306
8308 static void strtof(float& f, const char* str, char** endptr) noexcept
8309 {
8310 f = std::strtof(str, endptr);
8311 }
8312
8314 static void strtof(double& f, const char* str, char** endptr) noexcept
8315 {
8316 f = std::strtod(str, endptr);
8317 }
8318
8320 static void strtof(long double& f, const char* str, char** endptr) noexcept
8321 {
8322 f = std::strtold(str, endptr);
8323 }
8324
8365 token_type scan_number() // lgtm [cpp/use-of-goto]
8366 {
8367 // reset token_buffer to store the number's bytes
8368 reset();
8369
8370 // the type of the parsed number; initially set to unsigned; will be
8371 // changed if minus sign, decimal point or exponent is read
8372 token_type number_type = token_type::value_unsigned;
8373
8374 // state (init): we just found out we need to scan a number
8375 switch (current)
8376 {
8377 case '-':
8378 {
8379 add(current);
8380 goto scan_number_minus;
8381 }
8382
8383 case '0':
8384 {
8385 add(current);
8386 goto scan_number_zero;
8387 }
8388
8389 case '1':
8390 case '2':
8391 case '3':
8392 case '4':
8393 case '5':
8394 case '6':
8395 case '7':
8396 case '8':
8397 case '9':
8398 {
8399 add(current);
8400 goto scan_number_any1;
8401 }
8402
8403 // all other characters are rejected outside scan_number()
8404 default: // LCOV_EXCL_LINE
8405 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8406 }
8407
8408scan_number_minus:
8409 // state: we just parsed a leading minus sign
8410 number_type = token_type::value_integer;
8411 switch (get())
8412 {
8413 case '0':
8414 {
8415 add(current);
8416 goto scan_number_zero;
8417 }
8418
8419 case '1':
8420 case '2':
8421 case '3':
8422 case '4':
8423 case '5':
8424 case '6':
8425 case '7':
8426 case '8':
8427 case '9':
8428 {
8429 add(current);
8430 goto scan_number_any1;
8431 }
8432
8433 default:
8434 {
8435 error_message = "invalid number; expected digit after '-'";
8436 return token_type::parse_error;
8437 }
8438 }
8439
8440scan_number_zero:
8441 // state: we just parse a zero (maybe with a leading minus sign)
8442 switch (get())
8443 {
8444 case '.':
8445 {
8446 add(decimal_point_char);
8447 goto scan_number_decimal1;
8448 }
8449
8450 case 'e':
8451 case 'E':
8452 {
8453 add(current);
8454 goto scan_number_exponent;
8455 }
8456
8457 default:
8458 goto scan_number_done;
8459 }
8460
8461scan_number_any1:
8462 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8463 switch (get())
8464 {
8465 case '0':
8466 case '1':
8467 case '2':
8468 case '3':
8469 case '4':
8470 case '5':
8471 case '6':
8472 case '7':
8473 case '8':
8474 case '9':
8475 {
8476 add(current);
8477 goto scan_number_any1;
8478 }
8479
8480 case '.':
8481 {
8482 add(decimal_point_char);
8483 goto scan_number_decimal1;
8484 }
8485
8486 case 'e':
8487 case 'E':
8488 {
8489 add(current);
8490 goto scan_number_exponent;
8491 }
8492
8493 default:
8494 goto scan_number_done;
8495 }
8496
8497scan_number_decimal1:
8498 // state: we just parsed a decimal point
8499 number_type = token_type::value_float;
8500 switch (get())
8501 {
8502 case '0':
8503 case '1':
8504 case '2':
8505 case '3':
8506 case '4':
8507 case '5':
8508 case '6':
8509 case '7':
8510 case '8':
8511 case '9':
8512 {
8513 add(current);
8514 goto scan_number_decimal2;
8515 }
8516
8517 default:
8518 {
8519 error_message = "invalid number; expected digit after '.'";
8520 return token_type::parse_error;
8521 }
8522 }
8523
8524scan_number_decimal2:
8525 // we just parsed at least one number after a decimal point
8526 switch (get())
8527 {
8528 case '0':
8529 case '1':
8530 case '2':
8531 case '3':
8532 case '4':
8533 case '5':
8534 case '6':
8535 case '7':
8536 case '8':
8537 case '9':
8538 {
8539 add(current);
8540 goto scan_number_decimal2;
8541 }
8542
8543 case 'e':
8544 case 'E':
8545 {
8546 add(current);
8547 goto scan_number_exponent;
8548 }
8549
8550 default:
8551 goto scan_number_done;
8552 }
8553
8554scan_number_exponent:
8555 // we just parsed an exponent
8556 number_type = token_type::value_float;
8557 switch (get())
8558 {
8559 case '+':
8560 case '-':
8561 {
8562 add(current);
8563 goto scan_number_sign;
8564 }
8565
8566 case '0':
8567 case '1':
8568 case '2':
8569 case '3':
8570 case '4':
8571 case '5':
8572 case '6':
8573 case '7':
8574 case '8':
8575 case '9':
8576 {
8577 add(current);
8578 goto scan_number_any2;
8579 }
8580
8581 default:
8582 {
8583 error_message =
8584 "invalid number; expected '+', '-', or digit after exponent";
8585 return token_type::parse_error;
8586 }
8587 }
8588
8589scan_number_sign:
8590 // we just parsed an exponent sign
8591 switch (get())
8592 {
8593 case '0':
8594 case '1':
8595 case '2':
8596 case '3':
8597 case '4':
8598 case '5':
8599 case '6':
8600 case '7':
8601 case '8':
8602 case '9':
8603 {
8604 add(current);
8605 goto scan_number_any2;
8606 }
8607
8608 default:
8609 {
8610 error_message = "invalid number; expected digit after exponent sign";
8611 return token_type::parse_error;
8612 }
8613 }
8614
8615scan_number_any2:
8616 // we just parsed a number after the exponent or exponent sign
8617 switch (get())
8618 {
8619 case '0':
8620 case '1':
8621 case '2':
8622 case '3':
8623 case '4':
8624 case '5':
8625 case '6':
8626 case '7':
8627 case '8':
8628 case '9':
8629 {
8630 add(current);
8631 goto scan_number_any2;
8632 }
8633
8634 default:
8635 goto scan_number_done;
8636 }
8637
8638scan_number_done:
8639 // unget the character after the number (we only read it to know that
8640 // we are done scanning a number)
8641 unget();
8642
8643 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8644 errno = 0;
8645
8646 // try to parse integers first and fall back to floats
8647 if (number_type == token_type::value_unsigned)
8648 {
8649 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8650
8651 // we checked the number format before
8652 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8653
8654 if (errno == 0)
8655 {
8656 value_unsigned = static_cast<number_unsigned_t>(x);
8657 if (value_unsigned == x)
8658 {
8659 return token_type::value_unsigned;
8660 }
8661 }
8662 }
8663 else if (number_type == token_type::value_integer)
8664 {
8665 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8666
8667 // we checked the number format before
8668 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8669
8670 if (errno == 0)
8671 {
8672 value_integer = static_cast<number_integer_t>(x);
8673 if (value_integer == x)
8674 {
8675 return token_type::value_integer;
8676 }
8677 }
8678 }
8679
8680 // this code is reached if we parse a floating-point number or if an
8681 // integer conversion above failed
8682 strtof(value_float, token_buffer.data(), &endptr);
8683
8684 // we checked the number format before
8685 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8686
8687 return token_type::value_float;
8688 }
8689
8696 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8697 token_type return_type)
8698 {
8699 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8700 for (std::size_t i = 1; i < length; ++i)
8701 {
8702 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8703 {
8704 error_message = "invalid literal";
8705 return token_type::parse_error;
8706 }
8707 }
8708 return return_type;
8709 }
8710
8712 // input management
8714
8716 void reset() noexcept
8717 {
8718 token_buffer.clear();
8719 token_string.clear();
8720 token_string.push_back(char_traits<char_type>::to_char_type(current));
8721 }
8722
8723 /*
8724 @brief get next character from the input
8725
8726 This function provides the interface to the used input adapter. It does
8727 not throw in case the input reached EOF, but returns a
8728 `char_traits<char>::eof()` in that case. Stores the scanned characters
8729 for use in error messages.
8730
8731 @return character read from the input
8732 */
8733 char_int_type get()
8734 {
8735 ++position.chars_read_total;
8736 ++position.chars_read_current_line;
8737
8738 if (next_unget)
8739 {
8740 // just reset the next_unget variable and work with current
8741 next_unget = false;
8742 }
8743 else
8744 {
8745 current = ia.get_character();
8746 }
8747
8748 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8749 {
8750 token_string.push_back(char_traits<char_type>::to_char_type(current));
8751 }
8752
8753 if (current == '\n')
8754 {
8755 ++position.lines_read;
8756 position.chars_read_current_line = 0;
8757 }
8758
8759 return current;
8760 }
8761
8770 void unget()
8771 {
8772 next_unget = true;
8773
8774 --position.chars_read_total;
8775
8776 // in case we "unget" a newline, we have to also decrement the lines_read
8777 if (position.chars_read_current_line == 0)
8778 {
8779 if (position.lines_read > 0)
8780 {
8781 --position.lines_read;
8782 }
8783 }
8784 else
8785 {
8786 --position.chars_read_current_line;
8787 }
8788
8789 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8790 {
8791 JSON_ASSERT(!token_string.empty());
8792 token_string.pop_back();
8793 }
8794 }
8795
8797 void add(char_int_type c)
8798 {
8799 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8800 }
8801
8802 public:
8804 // value getters
8806
8808 constexpr number_integer_t get_number_integer() const noexcept
8809 {
8810 return value_integer;
8811 }
8812
8814 constexpr number_unsigned_t get_number_unsigned() const noexcept
8815 {
8816 return value_unsigned;
8817 }
8818
8820 constexpr number_float_t get_number_float() const noexcept
8821 {
8822 return value_float;
8823 }
8824
8826 string_t& get_string()
8827 {
8828 return token_buffer;
8829 }
8830
8832 // diagnostics
8834
8836 constexpr position_t get_position() const noexcept
8837 {
8838 return position;
8839 }
8840
8844 std::string get_token_string() const
8845 {
8846 // escape control characters
8847 std::string result;
8848 for (const auto c : token_string)
8849 {
8850 if (static_cast<unsigned char>(c) <= '\x1F')
8851 {
8852 // escape control characters
8853 std::array<char, 9> cs{{}};
8854 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8855 result += cs.data();
8856 }
8857 else
8858 {
8859 // add character as is
8860 result.push_back(static_cast<std::string::value_type>(c));
8861 }
8862 }
8863
8864 return result;
8865 }
8866
8869 constexpr const char* get_error_message() const noexcept
8870 {
8871 return error_message;
8872 }
8873
8875 // actual scanner
8877
8883 {
8884 if (get() == 0xEF)
8885 {
8886 // check if we completely parse the BOM
8887 return get() == 0xBB && get() == 0xBF;
8888 }
8889
8890 // the first character is not the beginning of the BOM; unget it to
8891 // process is later
8892 unget();
8893 return true;
8894 }
8895
8897 {
8898 do
8899 {
8900 get();
8901 }
8902 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8903 }
8904
8906 {
8907 // initially, skip the BOM
8908 if (position.chars_read_total == 0 && !skip_bom())
8909 {
8910 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8911 return token_type::parse_error;
8912 }
8913
8914 // read next character and ignore whitespace
8915 skip_whitespace();
8916
8917 // ignore comments
8918 while (ignore_comments && current == '/')
8919 {
8920 if (!scan_comment())
8921 {
8922 return token_type::parse_error;
8923 }
8924
8925 // skip following whitespace
8926 skip_whitespace();
8927 }
8928
8929 switch (current)
8930 {
8931 // structural characters
8932 case '[':
8933 return token_type::begin_array;
8934 case ']':
8935 return token_type::end_array;
8936 case '{':
8937 return token_type::begin_object;
8938 case '}':
8939 return token_type::end_object;
8940 case ':':
8941 return token_type::name_separator;
8942 case ',':
8943 return token_type::value_separator;
8944
8945 // literals
8946 case 't':
8947 {
8948 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8949 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8950 }
8951 case 'f':
8952 {
8953 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8954 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8955 }
8956 case 'n':
8957 {
8958 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8959 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8960 }
8961
8962 // string
8963 case '\"':
8964 return scan_string();
8965
8966 // number
8967 case '-':
8968 case '0':
8969 case '1':
8970 case '2':
8971 case '3':
8972 case '4':
8973 case '5':
8974 case '6':
8975 case '7':
8976 case '8':
8977 case '9':
8978 return scan_number();
8979
8980 // end of input (the null byte is needed when parsing from
8981 // string literals)
8982 case '\0':
8984 return token_type::end_of_input;
8985
8986 // error
8987 default:
8988 error_message = "invalid literal";
8989 return token_type::parse_error;
8990 }
8991 }
8992
8993 private:
8995 InputAdapterType ia;
8996
8998 const bool ignore_comments = false;
8999
9001 char_int_type current = char_traits<char_type>::eof();
9002
9004 bool next_unget = false;
9005
9007 position_t position {};
9008
9010 std::vector<char_type> token_string {};
9011
9013 string_t token_buffer {};
9014
9016 const char* error_message = "";
9017
9018 // number values
9019 number_integer_t value_integer = 0;
9020 number_unsigned_t value_unsigned = 0;
9021 number_float_t value_float = 0;
9022
9024 const char_int_type decimal_point_char = '.';
9025};
9026
9027} // namespace detail
9029
9030// #include <nlohmann/detail/macro_scope.hpp>
9031
9032// #include <nlohmann/detail/meta/is_sax.hpp>
9033// __ _____ _____ _____
9034// __| | __| | | | JSON for Modern C++
9035// | | |__ | | | | | | version 3.11.3
9036// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9037//
9038// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9039// SPDX-License-Identifier: MIT
9040
9041
9042
9043#include <cstdint> // size_t
9044#include <utility> // declval
9045#include <string> // string
9046
9047// #include <nlohmann/detail/abi_macros.hpp>
9048
9049// #include <nlohmann/detail/meta/detected.hpp>
9050
9051// #include <nlohmann/detail/meta/type_traits.hpp>
9052
9053
9055namespace detail
9056{
9057
9058template<typename T>
9059using null_function_t = decltype(std::declval<T&>().null());
9060
9061template<typename T>
9063 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9064
9065template<typename T, typename Integer>
9067 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9068
9069template<typename T, typename Unsigned>
9071 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9072
9073template<typename T, typename Float, typename String>
9074using number_float_function_t = decltype(std::declval<T&>().number_float(
9075 std::declval<Float>(), std::declval<const String&>()));
9076
9077template<typename T, typename String>
9079 decltype(std::declval<T&>().string(std::declval<String&>()));
9080
9081template<typename T, typename Binary>
9083 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9084
9085template<typename T>
9087 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9088
9089template<typename T, typename String>
9091 decltype(std::declval<T&>().key(std::declval<String&>()));
9092
9093template<typename T>
9094using end_object_function_t = decltype(std::declval<T&>().end_object());
9095
9096template<typename T>
9098 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9099
9100template<typename T>
9101using end_array_function_t = decltype(std::declval<T&>().end_array());
9102
9103template<typename T, typename Exception>
9104using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9105 std::declval<std::size_t>(), std::declval<const std::string&>(),
9106 std::declval<const Exception&>()));
9107
9108template<typename SAX, typename BasicJsonType>
9110{
9111 private:
9113 "BasicJsonType must be of type basic_json<...>");
9114
9115 using number_integer_t = typename BasicJsonType::number_integer_t;
9116 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9117 using number_float_t = typename BasicJsonType::number_float_t;
9118 using string_t = typename BasicJsonType::string_t;
9119 using binary_t = typename BasicJsonType::binary_t;
9120 using exception_t = typename BasicJsonType::exception;
9121
9122 public:
9123 static constexpr bool value =
9137};
9138
9139template<typename SAX, typename BasicJsonType>
9141{
9142 private:
9144 "BasicJsonType must be of type basic_json<...>");
9145
9146 using number_integer_t = typename BasicJsonType::number_integer_t;
9147 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9148 using number_float_t = typename BasicJsonType::number_float_t;
9149 using string_t = typename BasicJsonType::string_t;
9150 using binary_t = typename BasicJsonType::binary_t;
9151 using exception_t = typename BasicJsonType::exception;
9152
9153 public:
9155 "Missing/invalid function: bool null()");
9157 "Missing/invalid function: bool boolean(bool)");
9159 "Missing/invalid function: bool boolean(bool)");
9160 static_assert(
9162 number_integer_t>::value,
9163 "Missing/invalid function: bool number_integer(number_integer_t)");
9164 static_assert(
9166 number_unsigned_t>::value,
9167 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9168 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9169 number_float_t, string_t>::value,
9170 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9171 static_assert(
9173 "Missing/invalid function: bool string(string_t&)");
9174 static_assert(
9176 "Missing/invalid function: bool binary(binary_t&)");
9178 "Missing/invalid function: bool start_object(std::size_t)");
9180 "Missing/invalid function: bool key(string_t&)");
9182 "Missing/invalid function: bool end_object()");
9184 "Missing/invalid function: bool start_array(std::size_t)");
9186 "Missing/invalid function: bool end_array()");
9187 static_assert(
9189 "Missing/invalid function: bool parse_error(std::size_t, const "
9190 "std::string&, const exception&)");
9191};
9192
9193} // namespace detail
9195
9196// #include <nlohmann/detail/meta/type_traits.hpp>
9197
9198// #include <nlohmann/detail/string_concat.hpp>
9199
9200// #include <nlohmann/detail/value_t.hpp>
9201
9202
9204namespace detail
9205{
9206
9209{
9210 error,
9211 ignore,
9212 store
9213};
9214
9222static inline bool little_endianness(int num = 1) noexcept
9223{
9224 return *reinterpret_cast<char*>(&num) == 1;
9225}
9226
9228// binary reader //
9230
9234template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9236{
9237 using number_integer_t = typename BasicJsonType::number_integer_t;
9238 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9239 using number_float_t = typename BasicJsonType::number_float_t;
9240 using string_t = typename BasicJsonType::string_t;
9241 using binary_t = typename BasicJsonType::binary_t;
9242 using json_sax_t = SAX;
9243 using char_type = typename InputAdapterType::char_type;
9244 using char_int_type = typename char_traits<char_type>::int_type;
9245
9246 public:
9252 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9253 {
9255 }
9256
9257 // make class move-only
9259 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9261 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9262 ~binary_reader() = default;
9263
9273 bool sax_parse(const input_format_t format,
9274 json_sax_t* sax_,
9275 const bool strict = true,
9276 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9277 {
9278 sax = sax_;
9279 bool result = false;
9280
9281 switch (format)
9282 {
9284 result = parse_bson_internal();
9285 break;
9286
9288 result = parse_cbor_internal(true, tag_handler);
9289 break;
9290
9292 result = parse_msgpack_internal();
9293 break;
9294
9297 result = parse_ubjson_internal();
9298 break;
9299
9300 case input_format_t::json: // LCOV_EXCL_LINE
9301 default: // LCOV_EXCL_LINE
9302 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9303 }
9304
9305 // strict mode: next byte must be EOF
9306 if (result && strict)
9307 {
9308 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9309 {
9310 get_ignore_noop();
9311 }
9312 else
9313 {
9314 get();
9315 }
9316
9318 {
9319 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9320 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9321 }
9322 }
9323
9324 return result;
9325 }
9326
9327 private:
9329 // BSON //
9331
9336 bool parse_bson_internal()
9337 {
9338 std::int32_t document_size{};
9339 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9340
9341 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9342 {
9343 return false;
9344 }
9345
9346 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9347 {
9348 return false;
9349 }
9350
9351 return sax->end_object();
9352 }
9353
9361 bool get_bson_cstr(string_t& result)
9362 {
9363 auto out = std::back_inserter(result);
9364 while (true)
9365 {
9366 get();
9367 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9368 {
9369 return false;
9370 }
9371 if (current == 0x00)
9372 {
9373 return true;
9374 }
9375 *out++ = static_cast<typename string_t::value_type>(current);
9376 }
9377 }
9378
9390 template<typename NumberType>
9391 bool get_bson_string(const NumberType len, string_t& result)
9392 {
9393 if (JSON_HEDLEY_UNLIKELY(len < 1))
9394 {
9395 auto last_token = get_token_string();
9396 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9397 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9398 }
9399
9400 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9401 }
9402
9412 template<typename NumberType>
9413 bool get_bson_binary(const NumberType len, binary_t& result)
9414 {
9415 if (JSON_HEDLEY_UNLIKELY(len < 0))
9416 {
9417 auto last_token = get_token_string();
9418 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9419 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9420 }
9421
9422 // All BSON binary values have a subtype
9423 std::uint8_t subtype{};
9424 get_number<std::uint8_t>(input_format_t::bson, subtype);
9425 result.set_subtype(subtype);
9426
9427 return get_binary(input_format_t::bson, len, result);
9428 }
9429
9440 bool parse_bson_element_internal(const char_int_type element_type,
9441 const std::size_t element_type_parse_position)
9442 {
9443 switch (element_type)
9444 {
9445 case 0x01: // double
9446 {
9447 double number{};
9448 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9449 }
9450
9451 case 0x02: // string
9452 {
9453 std::int32_t len{};
9454 string_t value;
9455 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9456 }
9457
9458 case 0x03: // object
9459 {
9460 return parse_bson_internal();
9461 }
9462
9463 case 0x04: // array
9464 {
9465 return parse_bson_array();
9466 }
9467
9468 case 0x05: // binary
9469 {
9470 std::int32_t len{};
9471 binary_t value;
9472 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9473 }
9474
9475 case 0x08: // boolean
9476 {
9477 return sax->boolean(get() != 0);
9478 }
9479
9480 case 0x0A: // null
9481 {
9482 return sax->null();
9483 }
9484
9485 case 0x10: // int32
9486 {
9487 std::int32_t value{};
9488 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9489 }
9490
9491 case 0x12: // int64
9492 {
9493 std::int64_t value{};
9494 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9495 }
9496
9497 default: // anything else not supported (yet)
9498 {
9499 std::array<char, 3> cr{{}};
9500 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9501 const std::string cr_str{cr.data()};
9502 return sax->parse_error(element_type_parse_position, cr_str,
9503 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9504 }
9505 }
9506 }
9507
9520 bool parse_bson_element_list(const bool is_array)
9521 {
9522 string_t key;
9523
9524 while (auto element_type = get())
9525 {
9526 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9527 {
9528 return false;
9529 }
9530
9531 const std::size_t element_type_parse_position = chars_read;
9532 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9533 {
9534 return false;
9535 }
9536
9537 if (!is_array && !sax->key(key))
9538 {
9539 return false;
9540 }
9541
9542 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9543 {
9544 return false;
9545 }
9546
9547 // get_bson_cstr only appends
9548 key.clear();
9549 }
9550
9551 return true;
9552 }
9553
9558 bool parse_bson_array()
9559 {
9560 std::int32_t document_size{};
9561 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9562
9563 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9564 {
9565 return false;
9566 }
9567
9568 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9569 {
9570 return false;
9571 }
9572
9573 return sax->end_array();
9574 }
9575
9577 // CBOR //
9579
9588 bool parse_cbor_internal(const bool get_char,
9589 const cbor_tag_handler_t tag_handler)
9590 {
9591 switch (get_char ? get() : current)
9592 {
9593 // EOF
9594 case char_traits<char_type>::eof():
9595 return unexpect_eof(input_format_t::cbor, "value");
9596
9597 // Integer 0x00..0x17 (0..23)
9598 case 0x00:
9599 case 0x01:
9600 case 0x02:
9601 case 0x03:
9602 case 0x04:
9603 case 0x05:
9604 case 0x06:
9605 case 0x07:
9606 case 0x08:
9607 case 0x09:
9608 case 0x0A:
9609 case 0x0B:
9610 case 0x0C:
9611 case 0x0D:
9612 case 0x0E:
9613 case 0x0F:
9614 case 0x10:
9615 case 0x11:
9616 case 0x12:
9617 case 0x13:
9618 case 0x14:
9619 case 0x15:
9620 case 0x16:
9621 case 0x17:
9622 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9623
9624 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9625 {
9626 std::uint8_t number{};
9627 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9628 }
9629
9630 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9631 {
9632 std::uint16_t number{};
9633 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9634 }
9635
9636 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9637 {
9638 std::uint32_t number{};
9639 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9640 }
9641
9642 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9643 {
9644 std::uint64_t number{};
9645 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9646 }
9647
9648 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9649 case 0x20:
9650 case 0x21:
9651 case 0x22:
9652 case 0x23:
9653 case 0x24:
9654 case 0x25:
9655 case 0x26:
9656 case 0x27:
9657 case 0x28:
9658 case 0x29:
9659 case 0x2A:
9660 case 0x2B:
9661 case 0x2C:
9662 case 0x2D:
9663 case 0x2E:
9664 case 0x2F:
9665 case 0x30:
9666 case 0x31:
9667 case 0x32:
9668 case 0x33:
9669 case 0x34:
9670 case 0x35:
9671 case 0x36:
9672 case 0x37:
9673 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9674
9675 case 0x38: // Negative integer (one-byte uint8_t follows)
9676 {
9677 std::uint8_t number{};
9678 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9679 }
9680
9681 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9682 {
9683 std::uint16_t number{};
9684 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9685 }
9686
9687 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9688 {
9689 std::uint32_t number{};
9690 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9691 }
9692
9693 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9694 {
9695 std::uint64_t number{};
9696 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9697 - static_cast<number_integer_t>(number));
9698 }
9699
9700 // Binary data (0x00..0x17 bytes follow)
9701 case 0x40:
9702 case 0x41:
9703 case 0x42:
9704 case 0x43:
9705 case 0x44:
9706 case 0x45:
9707 case 0x46:
9708 case 0x47:
9709 case 0x48:
9710 case 0x49:
9711 case 0x4A:
9712 case 0x4B:
9713 case 0x4C:
9714 case 0x4D:
9715 case 0x4E:
9716 case 0x4F:
9717 case 0x50:
9718 case 0x51:
9719 case 0x52:
9720 case 0x53:
9721 case 0x54:
9722 case 0x55:
9723 case 0x56:
9724 case 0x57:
9725 case 0x58: // Binary data (one-byte uint8_t for n follows)
9726 case 0x59: // Binary data (two-byte uint16_t for n follow)
9727 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9728 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9729 case 0x5F: // Binary data (indefinite length)
9730 {
9731 binary_t b;
9732 return get_cbor_binary(b) && sax->binary(b);
9733 }
9734
9735 // UTF-8 string (0x00..0x17 bytes follow)
9736 case 0x60:
9737 case 0x61:
9738 case 0x62:
9739 case 0x63:
9740 case 0x64:
9741 case 0x65:
9742 case 0x66:
9743 case 0x67:
9744 case 0x68:
9745 case 0x69:
9746 case 0x6A:
9747 case 0x6B:
9748 case 0x6C:
9749 case 0x6D:
9750 case 0x6E:
9751 case 0x6F:
9752 case 0x70:
9753 case 0x71:
9754 case 0x72:
9755 case 0x73:
9756 case 0x74:
9757 case 0x75:
9758 case 0x76:
9759 case 0x77:
9760 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9761 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9762 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9763 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9764 case 0x7F: // UTF-8 string (indefinite length)
9765 {
9766 string_t s;
9767 return get_cbor_string(s) && sax->string(s);
9768 }
9769
9770 // array (0x00..0x17 data items follow)
9771 case 0x80:
9772 case 0x81:
9773 case 0x82:
9774 case 0x83:
9775 case 0x84:
9776 case 0x85:
9777 case 0x86:
9778 case 0x87:
9779 case 0x88:
9780 case 0x89:
9781 case 0x8A:
9782 case 0x8B:
9783 case 0x8C:
9784 case 0x8D:
9785 case 0x8E:
9786 case 0x8F:
9787 case 0x90:
9788 case 0x91:
9789 case 0x92:
9790 case 0x93:
9791 case 0x94:
9792 case 0x95:
9793 case 0x96:
9794 case 0x97:
9795 return get_cbor_array(
9796 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9797
9798 case 0x98: // array (one-byte uint8_t for n follows)
9799 {
9800 std::uint8_t len{};
9801 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9802 }
9803
9804 case 0x99: // array (two-byte uint16_t for n follow)
9805 {
9806 std::uint16_t len{};
9807 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9808 }
9809
9810 case 0x9A: // array (four-byte uint32_t for n follow)
9811 {
9812 std::uint32_t len{};
9813 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9814 }
9815
9816 case 0x9B: // array (eight-byte uint64_t for n follow)
9817 {
9818 std::uint64_t len{};
9819 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9820 }
9821
9822 case 0x9F: // array (indefinite length)
9823 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9824
9825 // map (0x00..0x17 pairs of data items follow)
9826 case 0xA0:
9827 case 0xA1:
9828 case 0xA2:
9829 case 0xA3:
9830 case 0xA4:
9831 case 0xA5:
9832 case 0xA6:
9833 case 0xA7:
9834 case 0xA8:
9835 case 0xA9:
9836 case 0xAA:
9837 case 0xAB:
9838 case 0xAC:
9839 case 0xAD:
9840 case 0xAE:
9841 case 0xAF:
9842 case 0xB0:
9843 case 0xB1:
9844 case 0xB2:
9845 case 0xB3:
9846 case 0xB4:
9847 case 0xB5:
9848 case 0xB6:
9849 case 0xB7:
9850 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9851
9852 case 0xB8: // map (one-byte uint8_t for n follows)
9853 {
9854 std::uint8_t len{};
9855 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9856 }
9857
9858 case 0xB9: // map (two-byte uint16_t for n follow)
9859 {
9860 std::uint16_t len{};
9861 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9862 }
9863
9864 case 0xBA: // map (four-byte uint32_t for n follow)
9865 {
9866 std::uint32_t len{};
9867 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9868 }
9869
9870 case 0xBB: // map (eight-byte uint64_t for n follow)
9871 {
9872 std::uint64_t len{};
9873 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9874 }
9875
9876 case 0xBF: // map (indefinite length)
9877 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9878
9879 case 0xC6: // tagged item
9880 case 0xC7:
9881 case 0xC8:
9882 case 0xC9:
9883 case 0xCA:
9884 case 0xCB:
9885 case 0xCC:
9886 case 0xCD:
9887 case 0xCE:
9888 case 0xCF:
9889 case 0xD0:
9890 case 0xD1:
9891 case 0xD2:
9892 case 0xD3:
9893 case 0xD4:
9894 case 0xD8: // tagged item (1 bytes follow)
9895 case 0xD9: // tagged item (2 bytes follow)
9896 case 0xDA: // tagged item (4 bytes follow)
9897 case 0xDB: // tagged item (8 bytes follow)
9898 {
9899 switch (tag_handler)
9900 {
9902 {
9903 auto last_token = get_token_string();
9904 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9905 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9906 }
9907
9909 {
9910 // ignore binary subtype
9911 switch (current)
9912 {
9913 case 0xD8:
9914 {
9915 std::uint8_t subtype_to_ignore{};
9916 get_number(input_format_t::cbor, subtype_to_ignore);
9917 break;
9918 }
9919 case 0xD9:
9920 {
9921 std::uint16_t subtype_to_ignore{};
9922 get_number(input_format_t::cbor, subtype_to_ignore);
9923 break;
9924 }
9925 case 0xDA:
9926 {
9927 std::uint32_t subtype_to_ignore{};
9928 get_number(input_format_t::cbor, subtype_to_ignore);
9929 break;
9930 }
9931 case 0xDB:
9932 {
9933 std::uint64_t subtype_to_ignore{};
9934 get_number(input_format_t::cbor, subtype_to_ignore);
9935 break;
9936 }
9937 default:
9938 break;
9939 }
9940 return parse_cbor_internal(true, tag_handler);
9941 }
9942
9944 {
9945 binary_t b;
9946 // use binary subtype and store in binary container
9947 switch (current)
9948 {
9949 case 0xD8:
9950 {
9951 std::uint8_t subtype{};
9952 get_number(input_format_t::cbor, subtype);
9954 break;
9955 }
9956 case 0xD9:
9957 {
9958 std::uint16_t subtype{};
9959 get_number(input_format_t::cbor, subtype);
9961 break;
9962 }
9963 case 0xDA:
9964 {
9965 std::uint32_t subtype{};
9966 get_number(input_format_t::cbor, subtype);
9968 break;
9969 }
9970 case 0xDB:
9971 {
9972 std::uint64_t subtype{};
9973 get_number(input_format_t::cbor, subtype);
9975 break;
9976 }
9977 default:
9978 return parse_cbor_internal(true, tag_handler);
9979 }
9980 get();
9981 return get_cbor_binary(b) && sax->binary(b);
9982 }
9983
9984 default: // LCOV_EXCL_LINE
9985 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9986 return false; // LCOV_EXCL_LINE
9987 }
9988 }
9989
9990 case 0xF4: // false
9991 return sax->boolean(false);
9992
9993 case 0xF5: // true
9994 return sax->boolean(true);
9995
9996 case 0xF6: // null
9997 return sax->null();
9998
9999 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10000 {
10001 const auto byte1_raw = get();
10002 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10003 {
10004 return false;
10005 }
10006 const auto byte2_raw = get();
10007 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10008 {
10009 return false;
10010 }
10011
10012 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10013 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10014
10015 // code from RFC 7049, Appendix D, Figure 3:
10016 // As half-precision floating-point numbers were only added
10017 // to IEEE 754 in 2008, today's programming platforms often
10018 // still only have limited support for them. It is very
10019 // easy to include at least decoding support for them even
10020 // without such support. An example of a small decoder for
10021 // half-precision floating-point numbers in the C language
10022 // is shown in Fig. 3.
10023 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10024 const double val = [&half]
10025 {
10026 const int exp = (half >> 10u) & 0x1Fu;
10027 const unsigned int mant = half & 0x3FFu;
10028 JSON_ASSERT(0 <= exp&& exp <= 32);
10029 JSON_ASSERT(mant <= 1024);
10030 switch (exp)
10031 {
10032 case 0:
10033 return std::ldexp(mant, -24);
10034 case 31:
10035 return (mant == 0)
10036 ? std::numeric_limits<double>::infinity()
10037 : std::numeric_limits<double>::quiet_NaN();
10038 default:
10039 return std::ldexp(mant + 1024, exp - 25);
10040 }
10041 }();
10042 return sax->number_float((half & 0x8000u) != 0
10043 ? static_cast<number_float_t>(-val)
10044 : static_cast<number_float_t>(val), "");
10045 }
10046
10047 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10048 {
10049 float number{};
10050 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10051 }
10052
10053 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10054 {
10055 double number{};
10056 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10057 }
10058
10059 default: // anything else (0xFF is handled inside the other types)
10060 {
10061 auto last_token = get_token_string();
10062 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10063 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10064 }
10065 }
10066 }
10067
10079 bool get_cbor_string(string_t& result)
10080 {
10081 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10082 {
10083 return false;
10084 }
10085
10086 switch (current)
10087 {
10088 // UTF-8 string (0x00..0x17 bytes follow)
10089 case 0x60:
10090 case 0x61:
10091 case 0x62:
10092 case 0x63:
10093 case 0x64:
10094 case 0x65:
10095 case 0x66:
10096 case 0x67:
10097 case 0x68:
10098 case 0x69:
10099 case 0x6A:
10100 case 0x6B:
10101 case 0x6C:
10102 case 0x6D:
10103 case 0x6E:
10104 case 0x6F:
10105 case 0x70:
10106 case 0x71:
10107 case 0x72:
10108 case 0x73:
10109 case 0x74:
10110 case 0x75:
10111 case 0x76:
10112 case 0x77:
10113 {
10114 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10115 }
10116
10117 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10118 {
10119 std::uint8_t len{};
10120 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10121 }
10122
10123 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10124 {
10125 std::uint16_t len{};
10126 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10127 }
10128
10129 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10130 {
10131 std::uint32_t len{};
10132 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10133 }
10134
10135 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10136 {
10137 std::uint64_t len{};
10138 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10139 }
10140
10141 case 0x7F: // UTF-8 string (indefinite length)
10142 {
10143 while (get() != 0xFF)
10144 {
10145 string_t chunk;
10146 if (!get_cbor_string(chunk))
10147 {
10148 return false;
10149 }
10150 result.append(chunk);
10151 }
10152 return true;
10153 }
10154
10155 default:
10156 {
10157 auto last_token = get_token_string();
10158 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10159 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10160 }
10161 }
10162 }
10163
10175 bool get_cbor_binary(binary_t& result)
10176 {
10177 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10178 {
10179 return false;
10180 }
10181
10182 switch (current)
10183 {
10184 // Binary data (0x00..0x17 bytes follow)
10185 case 0x40:
10186 case 0x41:
10187 case 0x42:
10188 case 0x43:
10189 case 0x44:
10190 case 0x45:
10191 case 0x46:
10192 case 0x47:
10193 case 0x48:
10194 case 0x49:
10195 case 0x4A:
10196 case 0x4B:
10197 case 0x4C:
10198 case 0x4D:
10199 case 0x4E:
10200 case 0x4F:
10201 case 0x50:
10202 case 0x51:
10203 case 0x52:
10204 case 0x53:
10205 case 0x54:
10206 case 0x55:
10207 case 0x56:
10208 case 0x57:
10209 {
10210 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10211 }
10212
10213 case 0x58: // Binary data (one-byte uint8_t for n follows)
10214 {
10215 std::uint8_t len{};
10216 return get_number(input_format_t::cbor, len) &&
10217 get_binary(input_format_t::cbor, len, result);
10218 }
10219
10220 case 0x59: // Binary data (two-byte uint16_t for n follow)
10221 {
10222 std::uint16_t len{};
10223 return get_number(input_format_t::cbor, len) &&
10224 get_binary(input_format_t::cbor, len, result);
10225 }
10226
10227 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10228 {
10229 std::uint32_t len{};
10230 return get_number(input_format_t::cbor, len) &&
10231 get_binary(input_format_t::cbor, len, result);
10232 }
10233
10234 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10235 {
10236 std::uint64_t len{};
10237 return get_number(input_format_t::cbor, len) &&
10238 get_binary(input_format_t::cbor, len, result);
10239 }
10240
10241 case 0x5F: // Binary data (indefinite length)
10242 {
10243 while (get() != 0xFF)
10244 {
10245 binary_t chunk;
10246 if (!get_cbor_binary(chunk))
10247 {
10248 return false;
10249 }
10250 result.insert(result.end(), chunk.begin(), chunk.end());
10251 }
10252 return true;
10253 }
10254
10255 default:
10256 {
10257 auto last_token = get_token_string();
10258 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10259 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10260 }
10261 }
10262 }
10263
10270 bool get_cbor_array(const std::size_t len,
10271 const cbor_tag_handler_t tag_handler)
10272 {
10273 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10274 {
10275 return false;
10276 }
10277
10278 if (len != static_cast<std::size_t>(-1))
10279 {
10280 for (std::size_t i = 0; i < len; ++i)
10281 {
10282 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10283 {
10284 return false;
10285 }
10286 }
10287 }
10288 else
10289 {
10290 while (get() != 0xFF)
10291 {
10292 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10293 {
10294 return false;
10295 }
10296 }
10297 }
10298
10299 return sax->end_array();
10300 }
10301
10308 bool get_cbor_object(const std::size_t len,
10309 const cbor_tag_handler_t tag_handler)
10310 {
10311 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10312 {
10313 return false;
10314 }
10315
10316 if (len != 0)
10317 {
10318 string_t key;
10319 if (len != static_cast<std::size_t>(-1))
10320 {
10321 for (std::size_t i = 0; i < len; ++i)
10322 {
10323 get();
10324 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10325 {
10326 return false;
10327 }
10328
10329 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10330 {
10331 return false;
10332 }
10333 key.clear();
10334 }
10335 }
10336 else
10337 {
10338 while (get() != 0xFF)
10339 {
10340 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10341 {
10342 return false;
10343 }
10344
10345 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10346 {
10347 return false;
10348 }
10349 key.clear();
10350 }
10351 }
10352 }
10353
10354 return sax->end_object();
10355 }
10356
10358 // MsgPack //
10360
10364 bool parse_msgpack_internal()
10365 {
10366 switch (get())
10367 {
10368 // EOF
10369 case char_traits<char_type>::eof():
10370 return unexpect_eof(input_format_t::msgpack, "value");
10371
10372 // positive fixint
10373 case 0x00:
10374 case 0x01:
10375 case 0x02:
10376 case 0x03:
10377 case 0x04:
10378 case 0x05:
10379 case 0x06:
10380 case 0x07:
10381 case 0x08:
10382 case 0x09:
10383 case 0x0A:
10384 case 0x0B:
10385 case 0x0C:
10386 case 0x0D:
10387 case 0x0E:
10388 case 0x0F:
10389 case 0x10:
10390 case 0x11:
10391 case 0x12:
10392 case 0x13:
10393 case 0x14:
10394 case 0x15:
10395 case 0x16:
10396 case 0x17:
10397 case 0x18:
10398 case 0x19:
10399 case 0x1A:
10400 case 0x1B:
10401 case 0x1C:
10402 case 0x1D:
10403 case 0x1E:
10404 case 0x1F:
10405 case 0x20:
10406 case 0x21:
10407 case 0x22:
10408 case 0x23:
10409 case 0x24:
10410 case 0x25:
10411 case 0x26:
10412 case 0x27:
10413 case 0x28:
10414 case 0x29:
10415 case 0x2A:
10416 case 0x2B:
10417 case 0x2C:
10418 case 0x2D:
10419 case 0x2E:
10420 case 0x2F:
10421 case 0x30:
10422 case 0x31:
10423 case 0x32:
10424 case 0x33:
10425 case 0x34:
10426 case 0x35:
10427 case 0x36:
10428 case 0x37:
10429 case 0x38:
10430 case 0x39:
10431 case 0x3A:
10432 case 0x3B:
10433 case 0x3C:
10434 case 0x3D:
10435 case 0x3E:
10436 case 0x3F:
10437 case 0x40:
10438 case 0x41:
10439 case 0x42:
10440 case 0x43:
10441 case 0x44:
10442 case 0x45:
10443 case 0x46:
10444 case 0x47:
10445 case 0x48:
10446 case 0x49:
10447 case 0x4A:
10448 case 0x4B:
10449 case 0x4C:
10450 case 0x4D:
10451 case 0x4E:
10452 case 0x4F:
10453 case 0x50:
10454 case 0x51:
10455 case 0x52:
10456 case 0x53:
10457 case 0x54:
10458 case 0x55:
10459 case 0x56:
10460 case 0x57:
10461 case 0x58:
10462 case 0x59:
10463 case 0x5A:
10464 case 0x5B:
10465 case 0x5C:
10466 case 0x5D:
10467 case 0x5E:
10468 case 0x5F:
10469 case 0x60:
10470 case 0x61:
10471 case 0x62:
10472 case 0x63:
10473 case 0x64:
10474 case 0x65:
10475 case 0x66:
10476 case 0x67:
10477 case 0x68:
10478 case 0x69:
10479 case 0x6A:
10480 case 0x6B:
10481 case 0x6C:
10482 case 0x6D:
10483 case 0x6E:
10484 case 0x6F:
10485 case 0x70:
10486 case 0x71:
10487 case 0x72:
10488 case 0x73:
10489 case 0x74:
10490 case 0x75:
10491 case 0x76:
10492 case 0x77:
10493 case 0x78:
10494 case 0x79:
10495 case 0x7A:
10496 case 0x7B:
10497 case 0x7C:
10498 case 0x7D:
10499 case 0x7E:
10500 case 0x7F:
10501 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10502
10503 // fixmap
10504 case 0x80:
10505 case 0x81:
10506 case 0x82:
10507 case 0x83:
10508 case 0x84:
10509 case 0x85:
10510 case 0x86:
10511 case 0x87:
10512 case 0x88:
10513 case 0x89:
10514 case 0x8A:
10515 case 0x8B:
10516 case 0x8C:
10517 case 0x8D:
10518 case 0x8E:
10519 case 0x8F:
10520 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10521
10522 // fixarray
10523 case 0x90:
10524 case 0x91:
10525 case 0x92:
10526 case 0x93:
10527 case 0x94:
10528 case 0x95:
10529 case 0x96:
10530 case 0x97:
10531 case 0x98:
10532 case 0x99:
10533 case 0x9A:
10534 case 0x9B:
10535 case 0x9C:
10536 case 0x9D:
10537 case 0x9E:
10538 case 0x9F:
10539 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10540
10541 // fixstr
10542 case 0xA0:
10543 case 0xA1:
10544 case 0xA2:
10545 case 0xA3:
10546 case 0xA4:
10547 case 0xA5:
10548 case 0xA6:
10549 case 0xA7:
10550 case 0xA8:
10551 case 0xA9:
10552 case 0xAA:
10553 case 0xAB:
10554 case 0xAC:
10555 case 0xAD:
10556 case 0xAE:
10557 case 0xAF:
10558 case 0xB0:
10559 case 0xB1:
10560 case 0xB2:
10561 case 0xB3:
10562 case 0xB4:
10563 case 0xB5:
10564 case 0xB6:
10565 case 0xB7:
10566 case 0xB8:
10567 case 0xB9:
10568 case 0xBA:
10569 case 0xBB:
10570 case 0xBC:
10571 case 0xBD:
10572 case 0xBE:
10573 case 0xBF:
10574 case 0xD9: // str 8
10575 case 0xDA: // str 16
10576 case 0xDB: // str 32
10577 {
10578 string_t s;
10579 return get_msgpack_string(s) && sax->string(s);
10580 }
10581
10582 case 0xC0: // nil
10583 return sax->null();
10584
10585 case 0xC2: // false
10586 return sax->boolean(false);
10587
10588 case 0xC3: // true
10589 return sax->boolean(true);
10590
10591 case 0xC4: // bin 8
10592 case 0xC5: // bin 16
10593 case 0xC6: // bin 32
10594 case 0xC7: // ext 8
10595 case 0xC8: // ext 16
10596 case 0xC9: // ext 32
10597 case 0xD4: // fixext 1
10598 case 0xD5: // fixext 2
10599 case 0xD6: // fixext 4
10600 case 0xD7: // fixext 8
10601 case 0xD8: // fixext 16
10602 {
10603 binary_t b;
10604 return get_msgpack_binary(b) && sax->binary(b);
10605 }
10606
10607 case 0xCA: // float 32
10608 {
10609 float number{};
10610 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10611 }
10612
10613 case 0xCB: // float 64
10614 {
10615 double number{};
10616 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10617 }
10618
10619 case 0xCC: // uint 8
10620 {
10621 std::uint8_t number{};
10622 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10623 }
10624
10625 case 0xCD: // uint 16
10626 {
10627 std::uint16_t number{};
10628 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10629 }
10630
10631 case 0xCE: // uint 32
10632 {
10633 std::uint32_t number{};
10634 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10635 }
10636
10637 case 0xCF: // uint 64
10638 {
10639 std::uint64_t number{};
10640 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10641 }
10642
10643 case 0xD0: // int 8
10644 {
10645 std::int8_t number{};
10646 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10647 }
10648
10649 case 0xD1: // int 16
10650 {
10651 std::int16_t number{};
10652 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10653 }
10654
10655 case 0xD2: // int 32
10656 {
10657 std::int32_t number{};
10658 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10659 }
10660
10661 case 0xD3: // int 64
10662 {
10663 std::int64_t number{};
10664 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10665 }
10666
10667 case 0xDC: // array 16
10668 {
10669 std::uint16_t len{};
10670 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10671 }
10672
10673 case 0xDD: // array 32
10674 {
10675 std::uint32_t len{};
10676 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10677 }
10678
10679 case 0xDE: // map 16
10680 {
10681 std::uint16_t len{};
10682 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10683 }
10684
10685 case 0xDF: // map 32
10686 {
10687 std::uint32_t len{};
10688 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10689 }
10690
10691 // negative fixint
10692 case 0xE0:
10693 case 0xE1:
10694 case 0xE2:
10695 case 0xE3:
10696 case 0xE4:
10697 case 0xE5:
10698 case 0xE6:
10699 case 0xE7:
10700 case 0xE8:
10701 case 0xE9:
10702 case 0xEA:
10703 case 0xEB:
10704 case 0xEC:
10705 case 0xED:
10706 case 0xEE:
10707 case 0xEF:
10708 case 0xF0:
10709 case 0xF1:
10710 case 0xF2:
10711 case 0xF3:
10712 case 0xF4:
10713 case 0xF5:
10714 case 0xF6:
10715 case 0xF7:
10716 case 0xF8:
10717 case 0xF9:
10718 case 0xFA:
10719 case 0xFB:
10720 case 0xFC:
10721 case 0xFD:
10722 case 0xFE:
10723 case 0xFF:
10724 return sax->number_integer(static_cast<std::int8_t>(current));
10725
10726 default: // anything else
10727 {
10728 auto last_token = get_token_string();
10729 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10730 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10731 }
10732 }
10733 }
10734
10745 bool get_msgpack_string(string_t& result)
10746 {
10747 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10748 {
10749 return false;
10750 }
10751
10752 switch (current)
10753 {
10754 // fixstr
10755 case 0xA0:
10756 case 0xA1:
10757 case 0xA2:
10758 case 0xA3:
10759 case 0xA4:
10760 case 0xA5:
10761 case 0xA6:
10762 case 0xA7:
10763 case 0xA8:
10764 case 0xA9:
10765 case 0xAA:
10766 case 0xAB:
10767 case 0xAC:
10768 case 0xAD:
10769 case 0xAE:
10770 case 0xAF:
10771 case 0xB0:
10772 case 0xB1:
10773 case 0xB2:
10774 case 0xB3:
10775 case 0xB4:
10776 case 0xB5:
10777 case 0xB6:
10778 case 0xB7:
10779 case 0xB8:
10780 case 0xB9:
10781 case 0xBA:
10782 case 0xBB:
10783 case 0xBC:
10784 case 0xBD:
10785 case 0xBE:
10786 case 0xBF:
10787 {
10788 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10789 }
10790
10791 case 0xD9: // str 8
10792 {
10793 std::uint8_t len{};
10794 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10795 }
10796
10797 case 0xDA: // str 16
10798 {
10799 std::uint16_t len{};
10800 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10801 }
10802
10803 case 0xDB: // str 32
10804 {
10805 std::uint32_t len{};
10806 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10807 }
10808
10809 default:
10810 {
10811 auto last_token = get_token_string();
10812 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10813 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10814 }
10815 }
10816 }
10817
10828 bool get_msgpack_binary(binary_t& result)
10829 {
10830 // helper function to set the subtype
10831 auto assign_and_return_true = [&result](std::int8_t subtype)
10832 {
10833 result.set_subtype(static_cast<std::uint8_t>(subtype));
10834 return true;
10835 };
10836
10837 switch (current)
10838 {
10839 case 0xC4: // bin 8
10840 {
10841 std::uint8_t len{};
10842 return get_number(input_format_t::msgpack, len) &&
10843 get_binary(input_format_t::msgpack, len, result);
10844 }
10845
10846 case 0xC5: // bin 16
10847 {
10848 std::uint16_t len{};
10849 return get_number(input_format_t::msgpack, len) &&
10850 get_binary(input_format_t::msgpack, len, result);
10851 }
10852
10853 case 0xC6: // bin 32
10854 {
10855 std::uint32_t len{};
10856 return get_number(input_format_t::msgpack, len) &&
10857 get_binary(input_format_t::msgpack, len, result);
10858 }
10859
10860 case 0xC7: // ext 8
10861 {
10862 std::uint8_t len{};
10863 std::int8_t subtype{};
10864 return get_number(input_format_t::msgpack, len) &&
10865 get_number(input_format_t::msgpack, subtype) &&
10866 get_binary(input_format_t::msgpack, len, result) &&
10867 assign_and_return_true(subtype);
10868 }
10869
10870 case 0xC8: // ext 16
10871 {
10872 std::uint16_t len{};
10873 std::int8_t subtype{};
10874 return get_number(input_format_t::msgpack, len) &&
10875 get_number(input_format_t::msgpack, subtype) &&
10876 get_binary(input_format_t::msgpack, len, result) &&
10877 assign_and_return_true(subtype);
10878 }
10879
10880 case 0xC9: // ext 32
10881 {
10882 std::uint32_t len{};
10883 std::int8_t subtype{};
10884 return get_number(input_format_t::msgpack, len) &&
10885 get_number(input_format_t::msgpack, subtype) &&
10886 get_binary(input_format_t::msgpack, len, result) &&
10887 assign_and_return_true(subtype);
10888 }
10889
10890 case 0xD4: // fixext 1
10891 {
10892 std::int8_t subtype{};
10893 return get_number(input_format_t::msgpack, subtype) &&
10894 get_binary(input_format_t::msgpack, 1, result) &&
10895 assign_and_return_true(subtype);
10896 }
10897
10898 case 0xD5: // fixext 2
10899 {
10900 std::int8_t subtype{};
10901 return get_number(input_format_t::msgpack, subtype) &&
10902 get_binary(input_format_t::msgpack, 2, result) &&
10903 assign_and_return_true(subtype);
10904 }
10905
10906 case 0xD6: // fixext 4
10907 {
10908 std::int8_t subtype{};
10909 return get_number(input_format_t::msgpack, subtype) &&
10910 get_binary(input_format_t::msgpack, 4, result) &&
10911 assign_and_return_true(subtype);
10912 }
10913
10914 case 0xD7: // fixext 8
10915 {
10916 std::int8_t subtype{};
10917 return get_number(input_format_t::msgpack, subtype) &&
10918 get_binary(input_format_t::msgpack, 8, result) &&
10919 assign_and_return_true(subtype);
10920 }
10921
10922 case 0xD8: // fixext 16
10923 {
10924 std::int8_t subtype{};
10925 return get_number(input_format_t::msgpack, subtype) &&
10926 get_binary(input_format_t::msgpack, 16, result) &&
10927 assign_and_return_true(subtype);
10928 }
10929
10930 default: // LCOV_EXCL_LINE
10931 return false; // LCOV_EXCL_LINE
10932 }
10933 }
10934
10939 bool get_msgpack_array(const std::size_t len)
10940 {
10941 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10942 {
10943 return false;
10944 }
10945
10946 for (std::size_t i = 0; i < len; ++i)
10947 {
10948 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10949 {
10950 return false;
10951 }
10952 }
10953
10954 return sax->end_array();
10955 }
10956
10961 bool get_msgpack_object(const std::size_t len)
10962 {
10963 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10964 {
10965 return false;
10966 }
10967
10968 string_t key;
10969 for (std::size_t i = 0; i < len; ++i)
10970 {
10971 get();
10972 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10973 {
10974 return false;
10975 }
10976
10977 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10978 {
10979 return false;
10980 }
10981 key.clear();
10982 }
10983
10984 return sax->end_object();
10985 }
10986
10988 // UBJSON //
10990
10998 bool parse_ubjson_internal(const bool get_char = true)
10999 {
11000 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11001 }
11002
11017 bool get_ubjson_string(string_t& result, const bool get_char = true)
11018 {
11019 if (get_char)
11020 {
11021 get(); // TODO(niels): may we ignore N here?
11022 }
11023
11024 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11025 {
11026 return false;
11027 }
11028
11029 switch (current)
11030 {
11031 case 'U':
11032 {
11033 std::uint8_t len{};
11034 return get_number(input_format, len) && get_string(input_format, len, result);
11035 }
11036
11037 case 'i':
11038 {
11039 std::int8_t len{};
11040 return get_number(input_format, len) && get_string(input_format, len, result);
11041 }
11042
11043 case 'I':
11044 {
11045 std::int16_t len{};
11046 return get_number(input_format, len) && get_string(input_format, len, result);
11047 }
11048
11049 case 'l':
11050 {
11051 std::int32_t len{};
11052 return get_number(input_format, len) && get_string(input_format, len, result);
11053 }
11054
11055 case 'L':
11056 {
11057 std::int64_t len{};
11058 return get_number(input_format, len) && get_string(input_format, len, result);
11059 }
11060
11061 case 'u':
11062 {
11063 if (input_format != input_format_t::bjdata)
11064 {
11065 break;
11066 }
11067 std::uint16_t len{};
11068 return get_number(input_format, len) && get_string(input_format, len, result);
11069 }
11070
11071 case 'm':
11072 {
11073 if (input_format != input_format_t::bjdata)
11074 {
11075 break;
11076 }
11077 std::uint32_t len{};
11078 return get_number(input_format, len) && get_string(input_format, len, result);
11079 }
11080
11081 case 'M':
11082 {
11083 if (input_format != input_format_t::bjdata)
11084 {
11085 break;
11086 }
11087 std::uint64_t len{};
11088 return get_number(input_format, len) && get_string(input_format, len, result);
11089 }
11090
11091 default:
11092 break;
11093 }
11094 auto last_token = get_token_string();
11095 std::string message;
11096
11097 if (input_format != input_format_t::bjdata)
11098 {
11099 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11100 }
11101 else
11102 {
11103 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11104 }
11105 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11106 }
11107
11112 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11113 {
11114 std::pair<std::size_t, char_int_type> size_and_type;
11115 size_t dimlen = 0;
11116 bool no_ndarray = true;
11117
11118 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11119 {
11120 return false;
11121 }
11122
11123 if (size_and_type.first != npos)
11124 {
11125 if (size_and_type.second != 0)
11126 {
11127 if (size_and_type.second != 'N')
11128 {
11129 for (std::size_t i = 0; i < size_and_type.first; ++i)
11130 {
11131 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11132 {
11133 return false;
11134 }
11135 dim.push_back(dimlen);
11136 }
11137 }
11138 }
11139 else
11140 {
11141 for (std::size_t i = 0; i < size_and_type.first; ++i)
11142 {
11143 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11144 {
11145 return false;
11146 }
11147 dim.push_back(dimlen);
11148 }
11149 }
11150 }
11151 else
11152 {
11153 while (current != ']')
11154 {
11155 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11156 {
11157 return false;
11158 }
11159 dim.push_back(dimlen);
11160 get_ignore_noop();
11161 }
11162 }
11163 return true;
11164 }
11165
11177 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11178 {
11179 if (prefix == 0)
11180 {
11181 prefix = get_ignore_noop();
11182 }
11183
11184 switch (prefix)
11185 {
11186 case 'U':
11187 {
11188 std::uint8_t number{};
11189 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11190 {
11191 return false;
11192 }
11193 result = static_cast<std::size_t>(number);
11194 return true;
11195 }
11196
11197 case 'i':
11198 {
11199 std::int8_t number{};
11200 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11201 {
11202 return false;
11203 }
11204 if (number < 0)
11205 {
11206 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11207 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11208 }
11209 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11210 return true;
11211 }
11212
11213 case 'I':
11214 {
11215 std::int16_t number{};
11216 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11217 {
11218 return false;
11219 }
11220 if (number < 0)
11221 {
11222 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11223 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11224 }
11225 result = static_cast<std::size_t>(number);
11226 return true;
11227 }
11228
11229 case 'l':
11230 {
11231 std::int32_t number{};
11232 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11233 {
11234 return false;
11235 }
11236 if (number < 0)
11237 {
11238 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11239 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11240 }
11241 result = static_cast<std::size_t>(number);
11242 return true;
11243 }
11244
11245 case 'L':
11246 {
11247 std::int64_t number{};
11248 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11249 {
11250 return false;
11251 }
11252 if (number < 0)
11253 {
11254 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11255 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11256 }
11257 if (!value_in_range_of<std::size_t>(number))
11258 {
11259 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11260 exception_message(input_format, "integer value overflow", "size"), nullptr));
11261 }
11262 result = static_cast<std::size_t>(number);
11263 return true;
11264 }
11265
11266 case 'u':
11267 {
11268 if (input_format != input_format_t::bjdata)
11269 {
11270 break;
11271 }
11272 std::uint16_t number{};
11273 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11274 {
11275 return false;
11276 }
11277 result = static_cast<std::size_t>(number);
11278 return true;
11279 }
11280
11281 case 'm':
11282 {
11283 if (input_format != input_format_t::bjdata)
11284 {
11285 break;
11286 }
11287 std::uint32_t number{};
11288 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11289 {
11290 return false;
11291 }
11292 result = conditional_static_cast<std::size_t>(number);
11293 return true;
11294 }
11295
11296 case 'M':
11297 {
11298 if (input_format != input_format_t::bjdata)
11299 {
11300 break;
11301 }
11302 std::uint64_t number{};
11303 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11304 {
11305 return false;
11306 }
11307 if (!value_in_range_of<std::size_t>(number))
11308 {
11309 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11310 exception_message(input_format, "integer value overflow", "size"), nullptr));
11311 }
11313 return true;
11314 }
11315
11316 case '[':
11317 {
11318 if (input_format != input_format_t::bjdata)
11319 {
11320 break;
11321 }
11322 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11323 {
11324 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11325 }
11326 std::vector<size_t> dim;
11327 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11328 {
11329 return false;
11330 }
11331 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11332 {
11333 result = dim.at(dim.size() - 1);
11334 return true;
11335 }
11336 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11337 {
11338 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11339 {
11340 if ( i == 0 )
11341 {
11342 result = 0;
11343 return true;
11344 }
11345 }
11346
11347 string_t key = "_ArraySize_";
11348 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11349 {
11350 return false;
11351 }
11352 result = 1;
11353 for (auto i : dim)
11354 {
11355 result *= i;
11356 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11357 {
11358 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11359 }
11360 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11361 {
11362 return false;
11363 }
11364 }
11365 is_ndarray = true;
11366 return sax->end_array();
11367 }
11368 result = 0;
11369 return true;
11370 }
11371
11372 default:
11373 break;
11374 }
11375 auto last_token = get_token_string();
11376 std::string message;
11377
11378 if (input_format != input_format_t::bjdata)
11379 {
11380 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11381 }
11382 else
11383 {
11384 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11385 }
11386 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11387 }
11388
11400 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11401 {
11402 result.first = npos; // size
11403 result.second = 0; // type
11404 bool is_ndarray = false;
11405
11406 get_ignore_noop();
11407
11408 if (current == '$')
11409 {
11410 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11411 if (input_format == input_format_t::bjdata
11412 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11413 {
11414 auto last_token = get_token_string();
11415 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11416 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11417 }
11418
11419 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11420 {
11421 return false;
11422 }
11423
11424 get_ignore_noop();
11425 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11426 {
11427 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11428 {
11429 return false;
11430 }
11431 auto last_token = get_token_string();
11432 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11433 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11434 }
11435
11436 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11437 if (input_format == input_format_t::bjdata && is_ndarray)
11438 {
11439 if (inside_ndarray)
11440 {
11441 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11442 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11443 }
11444 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11445 }
11446 return is_error;
11447 }
11448
11449 if (current == '#')
11450 {
11451 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11452 if (input_format == input_format_t::bjdata && is_ndarray)
11453 {
11454 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11455 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11456 }
11457 return is_error;
11458 }
11459
11460 return true;
11461 }
11462
11467 bool get_ubjson_value(const char_int_type prefix)
11468 {
11469 switch (prefix)
11470 {
11471 case char_traits<char_type>::eof(): // EOF
11472 return unexpect_eof(input_format, "value");
11473
11474 case 'T': // true
11475 return sax->boolean(true);
11476 case 'F': // false
11477 return sax->boolean(false);
11478
11479 case 'Z': // null
11480 return sax->null();
11481
11482 case 'U':
11483 {
11484 std::uint8_t number{};
11485 return get_number(input_format, number) && sax->number_unsigned(number);
11486 }
11487
11488 case 'i':
11489 {
11490 std::int8_t number{};
11491 return get_number(input_format, number) && sax->number_integer(number);
11492 }
11493
11494 case 'I':
11495 {
11496 std::int16_t number{};
11497 return get_number(input_format, number) && sax->number_integer(number);
11498 }
11499
11500 case 'l':
11501 {
11502 std::int32_t number{};
11503 return get_number(input_format, number) && sax->number_integer(number);
11504 }
11505
11506 case 'L':
11507 {
11508 std::int64_t number{};
11509 return get_number(input_format, number) && sax->number_integer(number);
11510 }
11511
11512 case 'u':
11513 {
11514 if (input_format != input_format_t::bjdata)
11515 {
11516 break;
11517 }
11518 std::uint16_t number{};
11519 return get_number(input_format, number) && sax->number_unsigned(number);
11520 }
11521
11522 case 'm':
11523 {
11524 if (input_format != input_format_t::bjdata)
11525 {
11526 break;
11527 }
11528 std::uint32_t number{};
11529 return get_number(input_format, number) && sax->number_unsigned(number);
11530 }
11531
11532 case 'M':
11533 {
11534 if (input_format != input_format_t::bjdata)
11535 {
11536 break;
11537 }
11538 std::uint64_t number{};
11539 return get_number(input_format, number) && sax->number_unsigned(number);
11540 }
11541
11542 case 'h':
11543 {
11544 if (input_format != input_format_t::bjdata)
11545 {
11546 break;
11547 }
11548 const auto byte1_raw = get();
11549 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11550 {
11551 return false;
11552 }
11553 const auto byte2_raw = get();
11554 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11555 {
11556 return false;
11557 }
11558
11559 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11560 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11561
11562 // code from RFC 7049, Appendix D, Figure 3:
11563 // As half-precision floating-point numbers were only added
11564 // to IEEE 754 in 2008, today's programming platforms often
11565 // still only have limited support for them. It is very
11566 // easy to include at least decoding support for them even
11567 // without such support. An example of a small decoder for
11568 // half-precision floating-point numbers in the C language
11569 // is shown in Fig. 3.
11570 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11571 const double val = [&half]
11572 {
11573 const int exp = (half >> 10u) & 0x1Fu;
11574 const unsigned int mant = half & 0x3FFu;
11575 JSON_ASSERT(0 <= exp&& exp <= 32);
11576 JSON_ASSERT(mant <= 1024);
11577 switch (exp)
11578 {
11579 case 0:
11580 return std::ldexp(mant, -24);
11581 case 31:
11582 return (mant == 0)
11583 ? std::numeric_limits<double>::infinity()
11584 : std::numeric_limits<double>::quiet_NaN();
11585 default:
11586 return std::ldexp(mant + 1024, exp - 25);
11587 }
11588 }();
11589 return sax->number_float((half & 0x8000u) != 0
11590 ? static_cast<number_float_t>(-val)
11591 : static_cast<number_float_t>(val), "");
11592 }
11593
11594 case 'd':
11595 {
11596 float number{};
11597 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11598 }
11599
11600 case 'D':
11601 {
11602 double number{};
11603 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11604 }
11605
11606 case 'H':
11607 {
11608 return get_ubjson_high_precision_number();
11609 }
11610
11611 case 'C': // char
11612 {
11613 get();
11614 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11615 {
11616 return false;
11617 }
11618 if (JSON_HEDLEY_UNLIKELY(current > 127))
11619 {
11620 auto last_token = get_token_string();
11621 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11622 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11623 }
11624 string_t s(1, static_cast<typename string_t::value_type>(current));
11625 return sax->string(s);
11626 }
11627
11628 case 'S': // string
11629 {
11630 string_t s;
11631 return get_ubjson_string(s) && sax->string(s);
11632 }
11633
11634 case '[': // array
11635 return get_ubjson_array();
11636
11637 case '{': // object
11638 return get_ubjson_object();
11639
11640 default: // anything else
11641 break;
11642 }
11643 auto last_token = get_token_string();
11644 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11645 }
11646
11650 bool get_ubjson_array()
11651 {
11652 std::pair<std::size_t, char_int_type> size_and_type;
11653 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11654 {
11655 return false;
11656 }
11657
11658 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11659 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11660
11661 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11662 {
11663 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11664 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11665 {
11666 return p.first < t;
11667 });
11668 string_t key = "_ArrayType_";
11669 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11670 {
11671 auto last_token = get_token_string();
11672 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11673 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11674 }
11675
11676 string_t type = it->second; // sax->string() takes a reference
11677 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11678 {
11679 return false;
11680 }
11681
11682 if (size_and_type.second == 'C')
11683 {
11684 size_and_type.second = 'U';
11685 }
11686
11687 key = "_ArrayData_";
11688 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11689 {
11690 return false;
11691 }
11692
11693 for (std::size_t i = 0; i < size_and_type.first; ++i)
11694 {
11695 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11696 {
11697 return false;
11698 }
11699 }
11700
11701 return (sax->end_array() && sax->end_object());
11702 }
11703
11704 if (size_and_type.first != npos)
11705 {
11706 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11707 {
11708 return false;
11709 }
11710
11711 if (size_and_type.second != 0)
11712 {
11713 if (size_and_type.second != 'N')
11714 {
11715 for (std::size_t i = 0; i < size_and_type.first; ++i)
11716 {
11717 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11718 {
11719 return false;
11720 }
11721 }
11722 }
11723 }
11724 else
11725 {
11726 for (std::size_t i = 0; i < size_and_type.first; ++i)
11727 {
11728 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11729 {
11730 return false;
11731 }
11732 }
11733 }
11734 }
11735 else
11736 {
11737 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11738 {
11739 return false;
11740 }
11741
11742 while (current != ']')
11743 {
11744 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11745 {
11746 return false;
11747 }
11748 get_ignore_noop();
11749 }
11750 }
11751
11752 return sax->end_array();
11753 }
11754
11758 bool get_ubjson_object()
11759 {
11760 std::pair<std::size_t, char_int_type> size_and_type;
11761 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11762 {
11763 return false;
11764 }
11765
11766 // do not accept ND-array size in objects in BJData
11767 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11768 {
11769 auto last_token = get_token_string();
11770 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11771 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11772 }
11773
11774 string_t key;
11775 if (size_and_type.first != npos)
11776 {
11777 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11778 {
11779 return false;
11780 }
11781
11782 if (size_and_type.second != 0)
11783 {
11784 for (std::size_t i = 0; i < size_and_type.first; ++i)
11785 {
11786 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11787 {
11788 return false;
11789 }
11790 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11791 {
11792 return false;
11793 }
11794 key.clear();
11795 }
11796 }
11797 else
11798 {
11799 for (std::size_t i = 0; i < size_and_type.first; ++i)
11800 {
11801 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11802 {
11803 return false;
11804 }
11805 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11806 {
11807 return false;
11808 }
11809 key.clear();
11810 }
11811 }
11812 }
11813 else
11814 {
11815 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11816 {
11817 return false;
11818 }
11819
11820 while (current != '}')
11821 {
11822 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11823 {
11824 return false;
11825 }
11826 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11827 {
11828 return false;
11829 }
11830 get_ignore_noop();
11831 key.clear();
11832 }
11833 }
11834
11835 return sax->end_object();
11836 }
11837
11838 // Note, no reader for UBJSON binary types is implemented because they do
11839 // not exist
11840
11841 bool get_ubjson_high_precision_number()
11842 {
11843 // get size of following number string
11844 std::size_t size{};
11845 bool no_ndarray = true;
11846 auto res = get_ubjson_size_value(size, no_ndarray);
11847 if (JSON_HEDLEY_UNLIKELY(!res))
11848 {
11849 return res;
11850 }
11851
11852 // get number string
11853 std::vector<char> number_vector;
11854 for (std::size_t i = 0; i < size; ++i)
11855 {
11856 get();
11857 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11858 {
11859 return false;
11860 }
11861 number_vector.push_back(static_cast<char>(current));
11862 }
11863
11864 // parse number string
11865 using ia_type = decltype(detail::input_adapter(number_vector));
11866 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11867 const auto result_number = number_lexer.scan();
11868 const auto number_string = number_lexer.get_token_string();
11869 const auto result_remainder = number_lexer.scan();
11870
11871 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11872
11873 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11874 {
11875 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11876 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11877 }
11878
11879 switch (result_number)
11880 {
11881 case token_type::value_integer:
11882 return sax->number_integer(number_lexer.get_number_integer());
11883 case token_type::value_unsigned:
11884 return sax->number_unsigned(number_lexer.get_number_unsigned());
11885 case token_type::value_float:
11886 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11887 case token_type::uninitialized:
11888 case token_type::literal_true:
11889 case token_type::literal_false:
11890 case token_type::literal_null:
11891 case token_type::value_string:
11892 case token_type::begin_array:
11893 case token_type::begin_object:
11894 case token_type::end_array:
11895 case token_type::end_object:
11896 case token_type::name_separator:
11897 case token_type::value_separator:
11898 case token_type::parse_error:
11899 case token_type::end_of_input:
11900 case token_type::literal_or_value:
11901 default:
11902 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11903 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11904 }
11905 }
11906
11908 // Utility functions //
11910
11920 char_int_type get()
11921 {
11922 ++chars_read;
11923 return current = ia.get_character();
11924 }
11925
11929 char_int_type get_ignore_noop()
11930 {
11931 do
11932 {
11933 get();
11934 }
11935 while (current == 'N');
11936
11937 return current;
11938 }
11939
11940 /*
11941 @brief read a number from the input
11942
11943 @tparam NumberType the type of the number
11944 @param[in] format the current format (for diagnostics)
11945 @param[out] result number of type @a NumberType
11946
11947 @return whether conversion completed
11948
11949 @note This function needs to respect the system's endianness, because
11950 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11951 (big endian) and therefore need reordering on little endian systems.
11952 On the other hand, BSON and BJData use little endian and should reorder
11953 on big endian systems.
11954 */
11955 template<typename NumberType, bool InputIsLittleEndian = false>
11956 bool get_number(const input_format_t format, NumberType& result)
11957 {
11958 // step 1: read input into array with system's byte order
11959 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11960 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11961 {
11962 get();
11963 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11964 {
11965 return false;
11966 }
11967
11968 // reverse byte order prior to conversion if necessary
11969 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11970 {
11971 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11972 }
11973 else
11974 {
11975 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11976 }
11977 }
11978
11979 // step 2: convert array into number of type T and return
11980 std::memcpy(&result, vec.data(), sizeof(NumberType));
11981 return true;
11982 }
11983
11998 template<typename NumberType>
11999 bool get_string(const input_format_t format,
12000 const NumberType len,
12001 string_t& result)
12002 {
12003 bool success = true;
12004 for (NumberType i = 0; i < len; i++)
12005 {
12006 get();
12007 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12008 {
12009 success = false;
12010 break;
12011 }
12012 result.push_back(static_cast<typename string_t::value_type>(current));
12013 }
12014 return success;
12015 }
12016
12031 template<typename NumberType>
12032 bool get_binary(const input_format_t format,
12033 const NumberType len,
12034 binary_t& result)
12035 {
12036 bool success = true;
12037 for (NumberType i = 0; i < len; i++)
12038 {
12039 get();
12040 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12041 {
12042 success = false;
12043 break;
12044 }
12045 result.push_back(static_cast<std::uint8_t>(current));
12046 }
12047 return success;
12048 }
12049
12056 bool unexpect_eof(const input_format_t format, const char* context) const
12057 {
12058 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12059 {
12060 return sax->parse_error(chars_read, "<end of file>",
12061 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12062 }
12063 return true;
12064 }
12065
12069 std::string get_token_string() const
12070 {
12071 std::array<char, 3> cr{{}};
12072 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12073 return std::string{cr.data()};
12074 }
12075
12082 std::string exception_message(const input_format_t format,
12083 const std::string& detail,
12084 const std::string& context) const
12085 {
12086 std::string error_msg = "syntax error while parsing ";
12087
12088 switch (format)
12089 {
12091 error_msg += "CBOR";
12092 break;
12093
12095 error_msg += "MessagePack";
12096 break;
12097
12099 error_msg += "UBJSON";
12100 break;
12101
12103 error_msg += "BSON";
12104 break;
12105
12107 error_msg += "BJData";
12108 break;
12109
12110 case input_format_t::json: // LCOV_EXCL_LINE
12111 default: // LCOV_EXCL_LINE
12112 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12113 }
12114
12115 return concat(error_msg, ' ', context, ": ", detail);
12116 }
12117
12118 private:
12119 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12120
12122 InputAdapterType ia;
12123
12125 char_int_type current = char_traits<char_type>::eof();
12126
12128 std::size_t chars_read = 0;
12129
12131 const bool is_little_endian = little_endianness();
12132
12134 const input_format_t input_format = input_format_t::json;
12135
12137 json_sax_t* sax = nullptr;
12138
12139 // excluded markers in bjdata optimized type
12140#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12141 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12142
12143#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12144 make_array<bjd_type>( \
12145 bjd_type{'C', "char"}, \
12146 bjd_type{'D', "double"}, \
12147 bjd_type{'I', "int16"}, \
12148 bjd_type{'L', "int64"}, \
12149 bjd_type{'M', "uint64"}, \
12150 bjd_type{'U', "uint8"}, \
12151 bjd_type{'d', "single"}, \
12152 bjd_type{'i', "int8"}, \
12153 bjd_type{'l', "int32"}, \
12154 bjd_type{'m', "uint32"}, \
12155 bjd_type{'u', "uint16"})
12156
12158 // lookup tables
12159 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12160 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12162
12163 using bjd_type = std::pair<char_int_type, string_t>;
12164 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12165 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12167
12168#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12169#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12170};
12171
12172#ifndef JSON_HAS_CPP_17
12173 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12174 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12175#endif
12176
12177} // namespace detail
12179
12180// #include <nlohmann/detail/input/input_adapters.hpp>
12181
12182// #include <nlohmann/detail/input/lexer.hpp>
12183
12184// #include <nlohmann/detail/input/parser.hpp>
12185// __ _____ _____ _____
12186// __| | __| | | | JSON for Modern C++
12187// | | |__ | | | | | | version 3.11.3
12188// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12189//
12190// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12191// SPDX-License-Identifier: MIT
12192
12193
12194
12195#include <cmath> // isfinite
12196#include <cstdint> // uint8_t
12197#include <functional> // function
12198#include <string> // string
12199#include <utility> // move
12200#include <vector> // vector
12201
12202// #include <nlohmann/detail/exceptions.hpp>
12203
12204// #include <nlohmann/detail/input/input_adapters.hpp>
12205
12206// #include <nlohmann/detail/input/json_sax.hpp>
12207
12208// #include <nlohmann/detail/input/lexer.hpp>
12209
12210// #include <nlohmann/detail/macro_scope.hpp>
12211
12212// #include <nlohmann/detail/meta/is_sax.hpp>
12213
12214// #include <nlohmann/detail/string_concat.hpp>
12215
12216// #include <nlohmann/detail/value_t.hpp>
12217
12218
12220namespace detail
12221{
12223// parser //
12225
12226enum class parse_event_t : std::uint8_t
12227{
12231 object_end,
12235 array_end,
12237 key,
12239 value
12240};
12241
12242template<typename BasicJsonType>
12244 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12245
12251template<typename BasicJsonType, typename InputAdapterType>
12253{
12254 using number_integer_t = typename BasicJsonType::number_integer_t;
12255 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12256 using number_float_t = typename BasicJsonType::number_float_t;
12257 using string_t = typename BasicJsonType::string_t;
12259 using token_type = typename lexer_t::token_type;
12260
12261 public:
12263 explicit parser(InputAdapterType&& adapter,
12264 const parser_callback_t<BasicJsonType> cb = nullptr,
12265 const bool allow_exceptions_ = true,
12266 const bool skip_comments = false)
12267 : callback(cb)
12268 , m_lexer(std::move(adapter), skip_comments)
12269 , allow_exceptions(allow_exceptions_)
12270 {
12271 // read first token
12272 get_token();
12273 }
12274
12285 void parse(const bool strict, BasicJsonType& result)
12286 {
12287 if (callback)
12288 {
12289 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12290 sax_parse_internal(&sdp);
12291
12292 // in strict mode, input must be completely read
12293 if (strict && (get_token() != token_type::end_of_input))
12294 {
12295 sdp.parse_error(m_lexer.get_position(),
12296 m_lexer.get_token_string(),
12297 parse_error::create(101, m_lexer.get_position(),
12298 exception_message(token_type::end_of_input, "value"), nullptr));
12299 }
12300
12301 // in case of an error, return discarded value
12302 if (sdp.is_errored())
12303 {
12304 result = value_t::discarded;
12305 return;
12306 }
12307
12308 // set top-level value to null if it was discarded by the callback
12309 // function
12310 if (result.is_discarded())
12311 {
12312 result = nullptr;
12313 }
12314 }
12315 else
12316 {
12317 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12318 sax_parse_internal(&sdp);
12319
12320 // in strict mode, input must be completely read
12321 if (strict && (get_token() != token_type::end_of_input))
12322 {
12323 sdp.parse_error(m_lexer.get_position(),
12324 m_lexer.get_token_string(),
12325 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12326 }
12327
12328 // in case of an error, return discarded value
12329 if (sdp.is_errored())
12330 {
12331 result = value_t::discarded;
12332 return;
12333 }
12334 }
12335
12336 result.assert_invariant();
12337 }
12338
12345 bool accept(const bool strict = true)
12346 {
12348 return sax_parse(&sax_acceptor, strict);
12349 }
12350
12351 template<typename SAX>
12353 bool sax_parse(SAX* sax, const bool strict = true)
12354 {
12356 const bool result = sax_parse_internal(sax);
12357
12358 // strict mode: next byte must be EOF
12359 if (result && strict && (get_token() != token_type::end_of_input))
12360 {
12361 return sax->parse_error(m_lexer.get_position(),
12362 m_lexer.get_token_string(),
12363 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12364 }
12365
12366 return result;
12367 }
12368
12369 private:
12370 template<typename SAX>
12372 bool sax_parse_internal(SAX* sax)
12373 {
12374 // stack to remember the hierarchy of structured values we are parsing
12375 // true = array; false = object
12376 std::vector<bool> states;
12377 // value to avoid a goto (see comment where set to true)
12378 bool skip_to_state_evaluation = false;
12379
12380 while (true)
12381 {
12382 if (!skip_to_state_evaluation)
12383 {
12384 // invariant: get_token() was called before each iteration
12385 switch (last_token)
12386 {
12387 case token_type::begin_object:
12388 {
12389 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12390 {
12391 return false;
12392 }
12393
12394 // closing } -> we are done
12395 if (get_token() == token_type::end_object)
12396 {
12397 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12398 {
12399 return false;
12400 }
12401 break;
12402 }
12403
12404 // parse key
12405 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12406 {
12407 return sax->parse_error(m_lexer.get_position(),
12408 m_lexer.get_token_string(),
12409 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12410 }
12411 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12412 {
12413 return false;
12414 }
12415
12416 // parse separator (:)
12417 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12418 {
12419 return sax->parse_error(m_lexer.get_position(),
12420 m_lexer.get_token_string(),
12421 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12422 }
12423
12424 // remember we are now inside an object
12425 states.push_back(false);
12426
12427 // parse values
12428 get_token();
12429 continue;
12430 }
12431
12432 case token_type::begin_array:
12433 {
12434 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12435 {
12436 return false;
12437 }
12438
12439 // closing ] -> we are done
12440 if (get_token() == token_type::end_array)
12441 {
12442 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12443 {
12444 return false;
12445 }
12446 break;
12447 }
12448
12449 // remember we are now inside an array
12450 states.push_back(true);
12451
12452 // parse values (no need to call get_token)
12453 continue;
12454 }
12455
12456 case token_type::value_float:
12457 {
12458 const auto res = m_lexer.get_number_float();
12459
12460 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12461 {
12462 return sax->parse_error(m_lexer.get_position(),
12463 m_lexer.get_token_string(),
12464 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12465 }
12466
12467 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12468 {
12469 return false;
12470 }
12471
12472 break;
12473 }
12474
12475 case token_type::literal_false:
12476 {
12477 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12478 {
12479 return false;
12480 }
12481 break;
12482 }
12483
12484 case token_type::literal_null:
12485 {
12486 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12487 {
12488 return false;
12489 }
12490 break;
12491 }
12492
12493 case token_type::literal_true:
12494 {
12495 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12496 {
12497 return false;
12498 }
12499 break;
12500 }
12501
12502 case token_type::value_integer:
12503 {
12504 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12505 {
12506 return false;
12507 }
12508 break;
12509 }
12510
12511 case token_type::value_string:
12512 {
12513 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12514 {
12515 return false;
12516 }
12517 break;
12518 }
12519
12520 case token_type::value_unsigned:
12521 {
12522 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12523 {
12524 return false;
12525 }
12526 break;
12527 }
12528
12529 case token_type::parse_error:
12530 {
12531 // using "uninitialized" to avoid "expected" message
12532 return sax->parse_error(m_lexer.get_position(),
12533 m_lexer.get_token_string(),
12534 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12535 }
12536 case token_type::end_of_input:
12537 {
12539 {
12540 return sax->parse_error(m_lexer.get_position(),
12541 m_lexer.get_token_string(),
12542 parse_error::create(101, m_lexer.get_position(),
12543 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12544 }
12545
12546 return sax->parse_error(m_lexer.get_position(),
12547 m_lexer.get_token_string(),
12548 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12549 }
12550 case token_type::uninitialized:
12551 case token_type::end_array:
12552 case token_type::end_object:
12553 case token_type::name_separator:
12554 case token_type::value_separator:
12555 case token_type::literal_or_value:
12556 default: // the last token was unexpected
12557 {
12558 return sax->parse_error(m_lexer.get_position(),
12559 m_lexer.get_token_string(),
12560 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12561 }
12562 }
12563 }
12564 else
12565 {
12566 skip_to_state_evaluation = false;
12567 }
12568
12569 // we reached this line after we successfully parsed a value
12570 if (states.empty())
12571 {
12572 // empty stack: we reached the end of the hierarchy: done
12573 return true;
12574 }
12575
12576 if (states.back()) // array
12577 {
12578 // comma -> next value
12579 if (get_token() == token_type::value_separator)
12580 {
12581 // parse a new value
12582 get_token();
12583 continue;
12584 }
12585
12586 // closing ]
12587 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12588 {
12589 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12590 {
12591 return false;
12592 }
12593
12594 // We are done with this array. Before we can parse a
12595 // new value, we need to evaluate the new state first.
12596 // By setting skip_to_state_evaluation to false, we
12597 // are effectively jumping to the beginning of this if.
12598 JSON_ASSERT(!states.empty());
12599 states.pop_back();
12600 skip_to_state_evaluation = true;
12601 continue;
12602 }
12603
12604 return sax->parse_error(m_lexer.get_position(),
12605 m_lexer.get_token_string(),
12606 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12607 }
12608
12609 // states.back() is false -> object
12610
12611 // comma -> next value
12612 if (get_token() == token_type::value_separator)
12613 {
12614 // parse key
12615 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12616 {
12617 return sax->parse_error(m_lexer.get_position(),
12618 m_lexer.get_token_string(),
12619 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12620 }
12621
12622 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12623 {
12624 return false;
12625 }
12626
12627 // parse separator (:)
12628 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12629 {
12630 return sax->parse_error(m_lexer.get_position(),
12631 m_lexer.get_token_string(),
12632 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12633 }
12634
12635 // parse values
12636 get_token();
12637 continue;
12638 }
12639
12640 // closing }
12641 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12642 {
12643 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12644 {
12645 return false;
12646 }
12647
12648 // We are done with this object. Before we can parse a
12649 // new value, we need to evaluate the new state first.
12650 // By setting skip_to_state_evaluation to false, we
12651 // are effectively jumping to the beginning of this if.
12652 JSON_ASSERT(!states.empty());
12653 states.pop_back();
12654 skip_to_state_evaluation = true;
12655 continue;
12656 }
12657
12658 return sax->parse_error(m_lexer.get_position(),
12659 m_lexer.get_token_string(),
12660 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12661 }
12662 }
12663
12665 token_type get_token()
12666 {
12667 return last_token = m_lexer.scan();
12668 }
12669
12670 std::string exception_message(const token_type expected, const std::string& context)
12671 {
12672 std::string error_msg = "syntax error ";
12673
12674 if (!context.empty())
12675 {
12676 error_msg += concat("while parsing ", context, ' ');
12677 }
12678
12679 error_msg += "- ";
12680
12681 if (last_token == token_type::parse_error)
12682 {
12683 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12684 m_lexer.get_token_string(), '\'');
12685 }
12686 else
12687 {
12688 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12689 }
12690
12691 if (expected != token_type::uninitialized)
12692 {
12693 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12694 }
12695
12696 return error_msg;
12697 }
12698
12699 private:
12701 const parser_callback_t<BasicJsonType> callback = nullptr;
12703 token_type last_token = token_type::uninitialized;
12705 lexer_t m_lexer;
12707 const bool allow_exceptions = true;
12708};
12709
12710} // namespace detail
12712
12713// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12714// __ _____ _____ _____
12715// __| | __| | | | JSON for Modern C++
12716// | | |__ | | | | | | version 3.11.3
12717// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12718//
12719// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12720// SPDX-License-Identifier: MIT
12721
12722
12723
12724// #include <nlohmann/detail/abi_macros.hpp>
12725
12726// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12727// __ _____ _____ _____
12728// __| | __| | | | JSON for Modern C++
12729// | | |__ | | | | | | version 3.11.3
12730// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12731//
12732// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12733// SPDX-License-Identifier: MIT
12734
12735
12736
12737#include <cstddef> // ptrdiff_t
12738#include <limits> // numeric_limits
12739
12740// #include <nlohmann/detail/macro_scope.hpp>
12741
12742
12744namespace detail
12745{
12746
12747/*
12748@brief an iterator for primitive JSON types
12749
12750This class models an iterator for primitive JSON types (boolean, number,
12751string). It's only purpose is to allow the iterator/const_iterator classes
12752to "iterate" over primitive values. Internally, the iterator is modeled by
12753a `difference_type` variable. Value begin_value (`0`) models the begin,
12754end_value (`1`) models past the end.
12755*/
12757{
12758 private:
12759 using difference_type = std::ptrdiff_t;
12760 static constexpr difference_type begin_value = 0;
12761 static constexpr difference_type end_value = begin_value + 1;
12762
12765 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12766
12767 public:
12768 constexpr difference_type get_value() const noexcept
12769 {
12770 return m_it;
12771 }
12772
12774 void set_begin() noexcept
12775 {
12776 m_it = begin_value;
12777 }
12778
12780 void set_end() noexcept
12781 {
12782 m_it = end_value;
12783 }
12784
12786 constexpr bool is_begin() const noexcept
12787 {
12788 return m_it == begin_value;
12789 }
12790
12792 constexpr bool is_end() const noexcept
12793 {
12794 return m_it == end_value;
12795 }
12796
12797 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12798 {
12799 return lhs.m_it == rhs.m_it;
12800 }
12801
12802 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12803 {
12804 return lhs.m_it < rhs.m_it;
12805 }
12806
12807 primitive_iterator_t operator+(difference_type n) noexcept
12808 {
12809 auto result = *this;
12810 result += n;
12811 return result;
12812 }
12813
12814 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12815 {
12816 return lhs.m_it - rhs.m_it;
12817 }
12818
12820 {
12821 ++m_it;
12822 return *this;
12823 }
12824
12825 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12826 {
12827 auto result = *this;
12828 ++m_it;
12829 return result;
12830 }
12831
12833 {
12834 --m_it;
12835 return *this;
12836 }
12837
12838 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12839 {
12840 auto result = *this;
12841 --m_it;
12842 return result;
12843 }
12844
12845 primitive_iterator_t& operator+=(difference_type n) noexcept
12846 {
12847 m_it += n;
12848 return *this;
12849 }
12850
12851 primitive_iterator_t& operator-=(difference_type n) noexcept
12852 {
12853 m_it -= n;
12854 return *this;
12855 }
12856};
12857
12858} // namespace detail
12860
12861
12863namespace detail
12864{
12865
12872template<typename BasicJsonType> struct internal_iterator
12873{
12875 typename BasicJsonType::object_t::iterator object_iterator {};
12877 typename BasicJsonType::array_t::iterator array_iterator {};
12880};
12881
12882} // namespace detail
12884
12885// #include <nlohmann/detail/iterators/iter_impl.hpp>
12886// __ _____ _____ _____
12887// __| | __| | | | JSON for Modern C++
12888// | | |__ | | | | | | version 3.11.3
12889// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12890//
12891// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12892// SPDX-License-Identifier: MIT
12893
12894
12895
12896#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12897#include <type_traits> // conditional, is_const, remove_const
12898
12899// #include <nlohmann/detail/exceptions.hpp>
12900
12901// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12902
12903// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12904
12905// #include <nlohmann/detail/macro_scope.hpp>
12906
12907// #include <nlohmann/detail/meta/cpp_future.hpp>
12908
12909// #include <nlohmann/detail/meta/type_traits.hpp>
12910
12911// #include <nlohmann/detail/value_t.hpp>
12912
12913
12915namespace detail
12916{
12917
12918// forward declare, to be able to friend it later on
12919template<typename IteratorType> class iteration_proxy;
12920template<typename IteratorType> class iteration_proxy_value;
12921
12938template<typename BasicJsonType>
12939class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12940{
12942 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12944 friend other_iter_impl;
12945 friend BasicJsonType;
12948
12949 using object_t = typename BasicJsonType::object_t;
12950 using array_t = typename BasicJsonType::array_t;
12951 // make sure BasicJsonType is basic_json or const basic_json
12953 "iter_impl only accepts (const) basic_json");
12954 // superficial check for the LegacyBidirectionalIterator named requirement
12955 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12956 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12957 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12958
12959 public:
12965 using iterator_category = std::bidirectional_iterator_tag;
12966
12968 using value_type = typename BasicJsonType::value_type;
12970 using difference_type = typename BasicJsonType::difference_type;
12972 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12973 typename BasicJsonType::const_pointer,
12974 typename BasicJsonType::pointer>::type;
12977 typename std::conditional<std::is_const<BasicJsonType>::value,
12978 typename BasicJsonType::const_reference,
12979 typename BasicJsonType::reference>::type;
12980
12981 iter_impl() = default;
12982 ~iter_impl() = default;
12983 iter_impl(iter_impl&&) noexcept = default;
12984 iter_impl& operator=(iter_impl&&) noexcept = default;
12985
12992 explicit iter_impl(pointer object) noexcept : m_object(object)
12993 {
12994 JSON_ASSERT(m_object != nullptr);
12995
12996 switch (m_object->m_data.m_type)
12997 {
12998 case value_t::object:
12999 {
13000 m_it.object_iterator = typename object_t::iterator();
13001 break;
13002 }
13003
13004 case value_t::array:
13005 {
13006 m_it.array_iterator = typename array_t::iterator();
13007 break;
13008 }
13009
13010 case value_t::null:
13011 case value_t::string:
13012 case value_t::boolean:
13016 case value_t::binary:
13017 case value_t::discarded:
13018 default:
13019 {
13020 m_it.primitive_iterator = primitive_iterator_t();
13021 break;
13022 }
13023 }
13024 }
13025
13043 : m_object(other.m_object), m_it(other.m_it)
13044 {}
13045
13053 {
13054 if (&other != this)
13055 {
13056 m_object = other.m_object;
13057 m_it = other.m_it;
13058 }
13059 return *this;
13060 }
13061
13067 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13068 : m_object(other.m_object), m_it(other.m_it)
13069 {}
13070
13077 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13078 {
13079 m_object = other.m_object;
13080 m_it = other.m_it;
13081 return *this;
13082 }
13083
13089 void set_begin() noexcept
13090 {
13091 JSON_ASSERT(m_object != nullptr);
13092
13093 switch (m_object->m_data.m_type)
13094 {
13095 case value_t::object:
13096 {
13097 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13098 break;
13099 }
13100
13101 case value_t::array:
13102 {
13103 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13104 break;
13105 }
13106
13107 case value_t::null:
13108 {
13109 // set to end so begin()==end() is true: null is empty
13110 m_it.primitive_iterator.set_end();
13111 break;
13112 }
13113
13114 case value_t::string:
13115 case value_t::boolean:
13119 case value_t::binary:
13120 case value_t::discarded:
13121 default:
13122 {
13123 m_it.primitive_iterator.set_begin();
13124 break;
13125 }
13126 }
13127 }
13128
13133 void set_end() noexcept
13134 {
13135 JSON_ASSERT(m_object != nullptr);
13136
13137 switch (m_object->m_data.m_type)
13138 {
13139 case value_t::object:
13140 {
13141 m_it.object_iterator = m_object->m_data.m_value.object->end();
13142 break;
13143 }
13144
13145 case value_t::array:
13146 {
13147 m_it.array_iterator = m_object->m_data.m_value.array->end();
13148 break;
13149 }
13150
13151 case value_t::null:
13152 case value_t::string:
13153 case value_t::boolean:
13157 case value_t::binary:
13158 case value_t::discarded:
13159 default:
13160 {
13161 m_it.primitive_iterator.set_end();
13162 break;
13163 }
13164 }
13165 }
13166
13167 public:
13173 {
13174 JSON_ASSERT(m_object != nullptr);
13175
13176 switch (m_object->m_data.m_type)
13177 {
13178 case value_t::object:
13179 {
13180 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13181 return m_it.object_iterator->second;
13182 }
13183
13184 case value_t::array:
13185 {
13186 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13187 return *m_it.array_iterator;
13188 }
13189
13190 case value_t::null:
13191 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13192
13193 case value_t::string:
13194 case value_t::boolean:
13198 case value_t::binary:
13199 case value_t::discarded:
13200 default:
13201 {
13202 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13203 {
13204 return *m_object;
13205 }
13206
13207 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13208 }
13209 }
13210 }
13211
13217 {
13218 JSON_ASSERT(m_object != nullptr);
13219
13220 switch (m_object->m_data.m_type)
13221 {
13222 case value_t::object:
13223 {
13224 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13225 return &(m_it.object_iterator->second);
13226 }
13227
13228 case value_t::array:
13229 {
13230 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13231 return &*m_it.array_iterator;
13232 }
13233
13234 case value_t::null:
13235 case value_t::string:
13236 case value_t::boolean:
13240 case value_t::binary:
13241 case value_t::discarded:
13242 default:
13243 {
13244 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13245 {
13246 return m_object;
13247 }
13248
13249 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13250 }
13251 }
13252 }
13253
13258 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13259 {
13260 auto result = *this;
13261 ++(*this);
13262 return result;
13263 }
13264
13270 {
13271 JSON_ASSERT(m_object != nullptr);
13272
13273 switch (m_object->m_data.m_type)
13274 {
13275 case value_t::object:
13276 {
13277 std::advance(m_it.object_iterator, 1);
13278 break;
13279 }
13280
13281 case value_t::array:
13282 {
13283 std::advance(m_it.array_iterator, 1);
13284 break;
13285 }
13286
13287 case value_t::null:
13288 case value_t::string:
13289 case value_t::boolean:
13293 case value_t::binary:
13294 case value_t::discarded:
13295 default:
13296 {
13297 ++m_it.primitive_iterator;
13298 break;
13299 }
13300 }
13301
13302 return *this;
13303 }
13304
13309 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13310 {
13311 auto result = *this;
13312 --(*this);
13313 return result;
13314 }
13315
13321 {
13322 JSON_ASSERT(m_object != nullptr);
13323
13324 switch (m_object->m_data.m_type)
13325 {
13326 case value_t::object:
13327 {
13328 std::advance(m_it.object_iterator, -1);
13329 break;
13330 }
13331
13332 case value_t::array:
13333 {
13334 std::advance(m_it.array_iterator, -1);
13335 break;
13336 }
13337
13338 case value_t::null:
13339 case value_t::string:
13340 case value_t::boolean:
13344 case value_t::binary:
13345 case value_t::discarded:
13346 default:
13347 {
13348 --m_it.primitive_iterator;
13349 break;
13350 }
13351 }
13352
13353 return *this;
13354 }
13355
13360 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13361 bool operator==(const IterImpl& other) const
13362 {
13363 // if objects are not the same, the comparison is undefined
13364 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13365 {
13366 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13367 }
13368
13369 JSON_ASSERT(m_object != nullptr);
13370
13371 switch (m_object->m_data.m_type)
13372 {
13373 case value_t::object:
13374 return (m_it.object_iterator == other.m_it.object_iterator);
13375
13376 case value_t::array:
13377 return (m_it.array_iterator == other.m_it.array_iterator);
13378
13379 case value_t::null:
13380 case value_t::string:
13381 case value_t::boolean:
13385 case value_t::binary:
13386 case value_t::discarded:
13387 default:
13388 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13389 }
13390 }
13391
13396 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13397 bool operator!=(const IterImpl& other) const
13398 {
13399 return !operator==(other);
13400 }
13401
13406 bool operator<(const iter_impl& other) const
13407 {
13408 // if objects are not the same, the comparison is undefined
13409 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13410 {
13411 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13412 }
13413
13414 JSON_ASSERT(m_object != nullptr);
13415
13416 switch (m_object->m_data.m_type)
13417 {
13418 case value_t::object:
13419 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13420
13421 case value_t::array:
13422 return (m_it.array_iterator < other.m_it.array_iterator);
13423
13424 case value_t::null:
13425 case value_t::string:
13426 case value_t::boolean:
13430 case value_t::binary:
13431 case value_t::discarded:
13432 default:
13433 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13434 }
13435 }
13436
13441 bool operator<=(const iter_impl& other) const
13442 {
13443 return !other.operator < (*this);
13444 }
13445
13450 bool operator>(const iter_impl& other) const
13451 {
13452 return !operator<=(other);
13453 }
13454
13459 bool operator>=(const iter_impl& other) const
13460 {
13461 return !operator<(other);
13462 }
13463
13469 {
13470 JSON_ASSERT(m_object != nullptr);
13471
13472 switch (m_object->m_data.m_type)
13473 {
13474 case value_t::object:
13475 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13476
13477 case value_t::array:
13478 {
13479 std::advance(m_it.array_iterator, i);
13480 break;
13481 }
13482
13483 case value_t::null:
13484 case value_t::string:
13485 case value_t::boolean:
13489 case value_t::binary:
13490 case value_t::discarded:
13491 default:
13492 {
13493 m_it.primitive_iterator += i;
13494 break;
13495 }
13496 }
13497
13498 return *this;
13499 }
13500
13506 {
13507 return operator+=(-i);
13508 }
13509
13515 {
13516 auto result = *this;
13517 result += i;
13518 return result;
13519 }
13520
13526 {
13527 auto result = it;
13528 result += i;
13529 return result;
13530 }
13531
13537 {
13538 auto result = *this;
13539 result -= i;
13540 return result;
13541 }
13542
13548 {
13549 JSON_ASSERT(m_object != nullptr);
13550
13551 switch (m_object->m_data.m_type)
13552 {
13553 case value_t::object:
13554 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13555
13556 case value_t::array:
13557 return m_it.array_iterator - other.m_it.array_iterator;
13558
13559 case value_t::null:
13560 case value_t::string:
13561 case value_t::boolean:
13565 case value_t::binary:
13566 case value_t::discarded:
13567 default:
13568 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13569 }
13570 }
13571
13577 {
13578 JSON_ASSERT(m_object != nullptr);
13579
13580 switch (m_object->m_data.m_type)
13581 {
13582 case value_t::object:
13583 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13584
13585 case value_t::array:
13586 return *std::next(m_it.array_iterator, n);
13587
13588 case value_t::null:
13589 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13590
13591 case value_t::string:
13592 case value_t::boolean:
13596 case value_t::binary:
13597 case value_t::discarded:
13598 default:
13599 {
13600 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13601 {
13602 return *m_object;
13603 }
13604
13605 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13606 }
13607 }
13608 }
13609
13614 const typename object_t::key_type& key() const
13615 {
13616 JSON_ASSERT(m_object != nullptr);
13617
13618 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13619 {
13620 return m_it.object_iterator->first;
13621 }
13622
13623 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13624 }
13625
13631 {
13632 return operator*();
13633 }
13634
13637 pointer m_object = nullptr;
13640};
13641
13642} // namespace detail
13644
13645// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13646
13647// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13648// __ _____ _____ _____
13649// __| | __| | | | JSON for Modern C++
13650// | | |__ | | | | | | version 3.11.3
13651// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13652//
13653// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13654// SPDX-License-Identifier: MIT
13655
13656
13657
13658#include <cstddef> // ptrdiff_t
13659#include <iterator> // reverse_iterator
13660#include <utility> // declval
13661
13662// #include <nlohmann/detail/abi_macros.hpp>
13663
13664
13666namespace detail
13667{
13668
13670// reverse_iterator //
13672
13691template<typename Base>
13692class json_reverse_iterator : public std::reverse_iterator<Base>
13693{
13694 public:
13695 using difference_type = std::ptrdiff_t;
13697 using base_iterator = std::reverse_iterator<Base>;
13699 using reference = typename Base::reference;
13700
13702 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13703 : base_iterator(it) {}
13704
13706 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13707
13709 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13710 {
13711 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13712 }
13713
13716 {
13717 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13718 }
13719
13721 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13722 {
13723 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13724 }
13725
13728 {
13729 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13730 }
13731
13734 {
13735 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13736 }
13737
13740 {
13741 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13742 }
13743
13746 {
13747 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13748 }
13749
13752 {
13753 return base_iterator(*this) - base_iterator(other);
13754 }
13755
13758 {
13759 return *(this->operator+(n));
13760 }
13761
13763 auto key() const -> decltype(std::declval<Base>().key())
13764 {
13765 auto it = --this->base();
13766 return it.key();
13767 }
13768
13771 {
13772 auto it = --this->base();
13773 return it.operator * ();
13774 }
13775};
13776
13777} // namespace detail
13779
13780// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13781
13782// #include <nlohmann/detail/json_custom_base_class.hpp>
13783// __ _____ _____ _____
13784// __| | __| | | | JSON for Modern C++
13785// | | |__ | | | | | | version 3.11.3
13786// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13787//
13788// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13789// SPDX-License-Identifier: MIT
13790
13791
13792
13793#include <type_traits> // conditional, is_same
13794
13795// #include <nlohmann/detail/abi_macros.hpp>
13796
13797
13799namespace detail
13800{
13801
13813
13814template<class T>
13815using json_base_class = typename std::conditional <
13816 std::is_same<T, void>::value,
13818 T
13819 >::type;
13820
13821} // namespace detail
13823
13824// #include <nlohmann/detail/json_pointer.hpp>
13825// __ _____ _____ _____
13826// __| | __| | | | JSON for Modern C++
13827// | | |__ | | | | | | version 3.11.3
13828// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13829//
13830// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13831// SPDX-License-Identifier: MIT
13832
13833
13834
13835#include <algorithm> // all_of
13836#include <cctype> // isdigit
13837#include <cerrno> // errno, ERANGE
13838#include <cstdlib> // strtoull
13839#ifndef JSON_NO_IO
13840 #include <iosfwd> // ostream
13841#endif // JSON_NO_IO
13842#include <limits> // max
13843#include <numeric> // accumulate
13844#include <string> // string
13845#include <utility> // move
13846#include <vector> // vector
13847
13848// #include <nlohmann/detail/exceptions.hpp>
13849
13850// #include <nlohmann/detail/macro_scope.hpp>
13851
13852// #include <nlohmann/detail/string_concat.hpp>
13853
13854// #include <nlohmann/detail/string_escape.hpp>
13855
13856// #include <nlohmann/detail/value_t.hpp>
13857
13858
13860
13863template<typename RefStringType>
13865{
13866 // allow basic_json to access private members
13868 friend class basic_json;
13869
13870 template<typename>
13871 friend class json_pointer;
13872
13873 template<typename T>
13874 struct string_t_helper
13875 {
13876 using type = T;
13877 };
13878
13880 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13881 {
13882 using type = StringType;
13883 };
13884
13885 public:
13886 // for backwards compatibility accept BasicJsonType
13887 using string_t = typename string_t_helper<RefStringType>::type;
13888
13891 explicit json_pointer(const string_t& s = "")
13892 : reference_tokens(split(s))
13893 {}
13894
13898 {
13899 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13900 string_t{},
13901 [](const string_t& a, const string_t& b)
13902 {
13903 return detail::concat(a, '/', detail::escape(b));
13904 });
13905 }
13906
13910 operator string_t() const
13911 {
13912 return to_string();
13913 }
13914
13915#ifndef JSON_NO_IO
13918 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13919 {
13920 o << ptr.to_string();
13921 return o;
13922 }
13923#endif
13924
13928 {
13929 reference_tokens.insert(reference_tokens.end(),
13930 ptr.reference_tokens.begin(),
13931 ptr.reference_tokens.end());
13932 return *this;
13933 }
13934
13938 {
13939 push_back(std::move(token));
13940 return *this;
13941 }
13942
13945 json_pointer& operator/=(std::size_t array_idx)
13946 {
13947 return *this /= std::to_string(array_idx);
13948 }
13949
13953 const json_pointer& rhs)
13954 {
13955 return json_pointer(lhs) /= rhs;
13956 }
13957
13960 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13961 {
13962 return json_pointer(lhs) /= std::move(token);
13963 }
13964
13967 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13968 {
13969 return json_pointer(lhs) /= array_idx;
13970 }
13971
13975 {
13976 if (empty())
13977 {
13978 return *this;
13979 }
13980
13981 json_pointer res = *this;
13982 res.pop_back();
13983 return res;
13984 }
13985
13989 {
13991 {
13992 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13993 }
13994
13995 reference_tokens.pop_back();
13996 }
13997
14000 const string_t& back() const
14001 {
14003 {
14004 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14005 }
14006
14007 return reference_tokens.back();
14008 }
14009
14012 void push_back(const string_t& token)
14013 {
14014 reference_tokens.push_back(token);
14015 }
14016
14019 void push_back(string_t&& token)
14020 {
14021 reference_tokens.push_back(std::move(token));
14022 }
14023
14026 bool empty() const noexcept
14027 {
14028 return reference_tokens.empty();
14029 }
14030
14031 private:
14042 template<typename BasicJsonType>
14043 static typename BasicJsonType::size_type array_index(const string_t& s)
14044 {
14045 using size_type = typename BasicJsonType::size_type;
14046
14047 // error condition (cf. RFC 6901, Sect. 4)
14048 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14049 {
14050 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14051 }
14052
14053 // error condition (cf. RFC 6901, Sect. 4)
14054 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14055 {
14056 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14057 }
14058
14059 const char* p = s.c_str();
14060 char* p_end = nullptr;
14061 errno = 0; // strtoull doesn't reset errno
14062 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14063 if (p == p_end // invalid input or empty string
14064 || errno == ERANGE // out of range
14065 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14066 {
14067 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14068 }
14069
14070 // only triggered on special platforms (like 32bit), see also
14071 // https://github.com/nlohmann/json/pull/2203
14072 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14073 {
14074 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14075 }
14076
14077 return static_cast<size_type>(res);
14078 }
14079
14081 json_pointer top() const
14082 {
14084 {
14085 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14086 }
14087
14088 json_pointer result = *this;
14089 result.reference_tokens = {reference_tokens[0]};
14090 return result;
14091 }
14092
14093 private:
14102 template<typename BasicJsonType>
14103 BasicJsonType& get_and_create(BasicJsonType& j) const
14104 {
14105 auto* result = &j;
14106
14107 // in case no reference tokens exist, return a reference to the JSON value
14108 // j which will be overwritten by a primitive value
14109 for (const auto& reference_token : reference_tokens)
14110 {
14111 switch (result->type())
14112 {
14114 {
14115 if (reference_token == "0")
14116 {
14117 // start a new array if reference token is 0
14118 result = &result->operator[](0);
14119 }
14120 else
14121 {
14122 // start a new object otherwise
14123 result = &result->operator[](reference_token);
14124 }
14125 break;
14126 }
14127
14129 {
14130 // create an entry in the object
14131 result = &result->operator[](reference_token);
14132 break;
14133 }
14134
14136 {
14137 // create an entry in the array
14138 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14139 break;
14140 }
14141
14142 /*
14143 The following code is only reached if there exists a reference
14144 token _and_ the current value is primitive. In this case, we have
14145 an error situation, because primitive values may only occur as
14146 single value; that is, with an empty list of reference tokens.
14147 */
14155 default:
14156 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14157 }
14158 }
14159
14160 return *result;
14161 }
14162
14182 template<typename BasicJsonType>
14183 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14184 {
14185 for (const auto& reference_token : reference_tokens)
14186 {
14187 // convert null values to arrays or objects before continuing
14188 if (ptr->is_null())
14189 {
14190 // check if reference token is a number
14191 const bool nums =
14192 std::all_of(reference_token.begin(), reference_token.end(),
14193 [](const unsigned char x)
14194 {
14195 return std::isdigit(x);
14196 });
14197
14198 // change value to array for numbers or "-" or to object otherwise
14199 *ptr = (nums || reference_token == "-")
14201 : detail::value_t::object;
14202 }
14203
14204 switch (ptr->type())
14205 {
14207 {
14208 // use unchecked object access
14209 ptr = &ptr->operator[](reference_token);
14210 break;
14211 }
14212
14214 {
14215 if (reference_token == "-")
14216 {
14217 // explicitly treat "-" as index beyond the end
14218 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14219 }
14220 else
14221 {
14222 // convert array index to number; unchecked access
14223 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14224 }
14225 break;
14226 }
14227
14236 default:
14237 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14238 }
14239 }
14240
14241 return *ptr;
14242 }
14243
14250 template<typename BasicJsonType>
14251 BasicJsonType& get_checked(BasicJsonType* ptr) const
14252 {
14253 for (const auto& reference_token : reference_tokens)
14254 {
14255 switch (ptr->type())
14256 {
14258 {
14259 // note: at performs range check
14260 ptr = &ptr->at(reference_token);
14261 break;
14262 }
14263
14265 {
14266 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14267 {
14268 // "-" always fails the range check
14270 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14271 ") is out of range"), ptr));
14272 }
14273
14274 // note: at performs range check
14275 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14276 break;
14277 }
14278
14287 default:
14288 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14289 }
14290 }
14291
14292 return *ptr;
14293 }
14294
14308 template<typename BasicJsonType>
14309 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14310 {
14311 for (const auto& reference_token : reference_tokens)
14312 {
14313 switch (ptr->type())
14314 {
14316 {
14317 // use unchecked object access
14318 ptr = &ptr->operator[](reference_token);
14319 break;
14320 }
14321
14323 {
14324 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14325 {
14326 // "-" cannot be used for const access
14327 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14328 }
14329
14330 // use unchecked array access
14331 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14332 break;
14333 }
14334
14343 default:
14344 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14345 }
14346 }
14347
14348 return *ptr;
14349 }
14350
14357 template<typename BasicJsonType>
14358 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14359 {
14360 for (const auto& reference_token : reference_tokens)
14361 {
14362 switch (ptr->type())
14363 {
14365 {
14366 // note: at performs range check
14367 ptr = &ptr->at(reference_token);
14368 break;
14369 }
14370
14372 {
14373 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14374 {
14375 // "-" always fails the range check
14377 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14378 ") is out of range"), ptr));
14379 }
14380
14381 // note: at performs range check
14382 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14383 break;
14384 }
14385
14394 default:
14395 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14396 }
14397 }
14398
14399 return *ptr;
14400 }
14401
14406 template<typename BasicJsonType>
14407 bool contains(const BasicJsonType* ptr) const
14408 {
14409 for (const auto& reference_token : reference_tokens)
14410 {
14411 switch (ptr->type())
14412 {
14414 {
14415 if (!ptr->contains(reference_token))
14416 {
14417 // we did not find the key in the object
14418 return false;
14419 }
14420
14421 ptr = &ptr->operator[](reference_token);
14422 break;
14423 }
14424
14426 {
14427 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14428 {
14429 // "-" always fails the range check
14430 return false;
14431 }
14432 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14433 {
14434 // invalid char
14435 return false;
14436 }
14437 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14438 {
14439 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14440 {
14441 // first char should be between '1' and '9'
14442 return false;
14443 }
14444 for (std::size_t i = 1; i < reference_token.size(); i++)
14445 {
14446 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14447 {
14448 // other char should be between '0' and '9'
14449 return false;
14450 }
14451 }
14452 }
14453
14454 const auto idx = array_index<BasicJsonType>(reference_token);
14455 if (idx >= ptr->size())
14456 {
14457 // index out of range
14458 return false;
14459 }
14460
14461 ptr = &ptr->operator[](idx);
14462 break;
14463 }
14464
14473 default:
14474 {
14475 // we do not expect primitive values if there is still a
14476 // reference token to process
14477 return false;
14478 }
14479 }
14480 }
14481
14482 // no reference token left means we found a primitive value
14483 return true;
14484 }
14485
14495 static std::vector<string_t> split(const string_t& reference_string)
14496 {
14497 std::vector<string_t> result;
14498
14499 // special case: empty reference string -> no reference tokens
14500 if (reference_string.empty())
14501 {
14502 return result;
14503 }
14504
14505 // check if nonempty reference string begins with slash
14506 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14507 {
14508 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14509 }
14510
14511 // extract the reference tokens:
14512 // - slash: position of the last read slash (or end of string)
14513 // - start: position after the previous slash
14514 for (
14515 // search for the first slash after the first character
14516 std::size_t slash = reference_string.find_first_of('/', 1),
14517 // set the beginning of the first reference token
14518 start = 1;
14519 // we can stop if start == 0 (if slash == string_t::npos)
14520 start != 0;
14521 // set the beginning of the next reference token
14522 // (will eventually be 0 if slash == string_t::npos)
14523 start = (slash == string_t::npos) ? 0 : slash + 1,
14524 // find next slash
14525 slash = reference_string.find_first_of('/', start))
14526 {
14527 // use the text between the beginning of the reference token
14528 // (start) and the last slash (slash).
14529 auto reference_token = reference_string.substr(start, slash - start);
14530
14531 // check reference tokens are properly escaped
14532 for (std::size_t pos = reference_token.find_first_of('~');
14533 pos != string_t::npos;
14534 pos = reference_token.find_first_of('~', pos + 1))
14535 {
14536 JSON_ASSERT(reference_token[pos] == '~');
14537
14538 // ~ must be followed by 0 or 1
14539 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14540 (reference_token[pos + 1] != '0' &&
14541 reference_token[pos + 1] != '1')))
14542 {
14543 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14544 }
14545 }
14546
14547 // finally, store the reference token
14548 detail::unescape(reference_token);
14549 result.push_back(reference_token);
14550 }
14551
14552 return result;
14553 }
14554
14555 private:
14563 template<typename BasicJsonType>
14564 static void flatten(const string_t& reference_string,
14565 const BasicJsonType& value,
14566 BasicJsonType& result)
14567 {
14568 switch (value.type())
14569 {
14571 {
14572 if (value.m_data.m_value.array->empty())
14573 {
14574 // flatten empty array as null
14575 result[reference_string] = nullptr;
14576 }
14577 else
14578 {
14579 // iterate array and use index as reference string
14580 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14581 {
14582 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14583 value.m_data.m_value.array->operator[](i), result);
14584 }
14585 }
14586 break;
14587 }
14588
14590 {
14591 if (value.m_data.m_value.object->empty())
14592 {
14593 // flatten empty object as null
14594 result[reference_string] = nullptr;
14595 }
14596 else
14597 {
14598 // iterate object and use keys as reference string
14599 for (const auto& element : *value.m_data.m_value.object)
14600 {
14601 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14602 }
14603 }
14604 break;
14605 }
14606
14615 default:
14616 {
14617 // add primitive value with its reference string
14618 result[reference_string] = value;
14619 break;
14620 }
14621 }
14622 }
14623
14634 template<typename BasicJsonType>
14635 static BasicJsonType
14636 unflatten(const BasicJsonType& value)
14637 {
14638 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14639 {
14640 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14641 }
14642
14643 BasicJsonType result;
14644
14645 // iterate the JSON object values
14646 for (const auto& element : *value.m_data.m_value.object)
14647 {
14648 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14649 {
14650 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14651 }
14652
14653 // assign value to reference pointed to by JSON pointer; Note that if
14654 // the JSON pointer is "" (i.e., points to the whole value), function
14655 // get_and_create returns a reference to result itself. An assignment
14656 // will then create a primitive value.
14657 json_pointer(element.first).get_and_create(result) = element.second;
14658 }
14659
14660 return result;
14661 }
14662
14663 // can't use conversion operator because of ambiguity
14664 json_pointer<string_t> convert() const&
14665 {
14667 result.reference_tokens = reference_tokens;
14668 return result;
14669 }
14670
14671 json_pointer<string_t> convert()&&
14672 {
14674 result.reference_tokens = std::move(reference_tokens);
14675 return result;
14676 }
14677
14678 public:
14679#if JSON_HAS_THREE_WAY_COMPARISON
14682 template<typename RefStringTypeRhs>
14683 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14684 {
14685 return reference_tokens == rhs.reference_tokens;
14686 }
14687
14690 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14691 bool operator==(const string_t& rhs) const
14692 {
14693 return *this == json_pointer(rhs);
14694 }
14695
14697 template<typename RefStringTypeRhs>
14698 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14699 {
14700 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14701 }
14702#else
14705 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14706 // NOLINTNEXTLINE(readability-redundant-declaration)
14707 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14708 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14709
14712 template<typename RefStringTypeLhs, typename StringType>
14713 // NOLINTNEXTLINE(readability-redundant-declaration)
14714 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14715 const StringType& rhs);
14716
14719 template<typename RefStringTypeRhs, typename StringType>
14720 // NOLINTNEXTLINE(readability-redundant-declaration)
14721 friend bool operator==(const StringType& lhs,
14723
14726 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14727 // NOLINTNEXTLINE(readability-redundant-declaration)
14728 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14729 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14730
14733 template<typename RefStringTypeLhs, typename StringType>
14734 // NOLINTNEXTLINE(readability-redundant-declaration)
14735 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14736 const StringType& rhs);
14737
14740 template<typename RefStringTypeRhs, typename StringType>
14741 // NOLINTNEXTLINE(readability-redundant-declaration)
14742 friend bool operator!=(const StringType& lhs,
14744
14746 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14747 // NOLINTNEXTLINE(readability-redundant-declaration)
14748 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14749 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14750#endif
14751
14752 private:
14754 std::vector<string_t> reference_tokens;
14755};
14756
14757#if !JSON_HAS_THREE_WAY_COMPARISON
14758// functions cannot be defined inside class due to ODR violations
14759template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14761 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14762{
14763 return lhs.reference_tokens == rhs.reference_tokens;
14764}
14765
14766template<typename RefStringTypeLhs,
14767 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14769inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14770 const StringType& rhs)
14771{
14772 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14773}
14774
14775template<typename RefStringTypeRhs,
14776 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14778inline bool operator==(const StringType& lhs,
14779 const json_pointer<RefStringTypeRhs>& rhs)
14780{
14781 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14782}
14783
14784template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14786 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14787{
14788 return !(lhs == rhs);
14789}
14790
14791template<typename RefStringTypeLhs,
14792 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14794inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14795 const StringType& rhs)
14796{
14797 return !(lhs == rhs);
14798}
14799
14800template<typename RefStringTypeRhs,
14801 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14803inline bool operator!=(const StringType& lhs,
14804 const json_pointer<RefStringTypeRhs>& rhs)
14805{
14806 return !(lhs == rhs);
14807}
14808
14809template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14811 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14812{
14813 return lhs.reference_tokens < rhs.reference_tokens;
14814}
14815#endif
14816
14818
14819// #include <nlohmann/detail/json_ref.hpp>
14820// __ _____ _____ _____
14821// __| | __| | | | JSON for Modern C++
14822// | | |__ | | | | | | version 3.11.3
14823// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14824//
14825// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14826// SPDX-License-Identifier: MIT
14827
14828
14829
14830#include <initializer_list>
14831#include <utility>
14832
14833// #include <nlohmann/detail/abi_macros.hpp>
14834
14835// #include <nlohmann/detail/meta/type_traits.hpp>
14836
14837
14839namespace detail
14840{
14841
14842template<typename BasicJsonType>
14844{
14845 public:
14846 using value_type = BasicJsonType;
14847
14849 : owned_value(std::move(value))
14850 {}
14851
14853 : value_ref(&value)
14854 {}
14855
14856 json_ref(std::initializer_list<json_ref> init)
14857 : owned_value(init)
14858 {}
14859
14860 template <
14861 class... Args,
14862 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14863 json_ref(Args && ... args)
14864 : owned_value(std::forward<Args>(args)...)
14865 {}
14866
14867 // class should be movable only
14868 json_ref(json_ref&&) noexcept = default;
14869 json_ref(const json_ref&) = delete;
14870 json_ref& operator=(const json_ref&) = delete;
14871 json_ref& operator=(json_ref&&) = delete;
14872 ~json_ref() = default;
14873
14875 {
14876 if (value_ref == nullptr)
14877 {
14878 return std::move(owned_value);
14879 }
14880 return *value_ref;
14881 }
14882
14883 value_type const& operator*() const
14884 {
14885 return value_ref ? *value_ref : owned_value;
14886 }
14887
14888 value_type const* operator->() const
14889 {
14890 return &** this;
14891 }
14892
14893 private:
14894 mutable value_type owned_value = nullptr;
14895 value_type const* value_ref = nullptr;
14896};
14897
14898} // namespace detail
14900
14901// #include <nlohmann/detail/macro_scope.hpp>
14902
14903// #include <nlohmann/detail/string_concat.hpp>
14904
14905// #include <nlohmann/detail/string_escape.hpp>
14906
14907// #include <nlohmann/detail/meta/cpp_future.hpp>
14908
14909// #include <nlohmann/detail/meta/type_traits.hpp>
14910
14911// #include <nlohmann/detail/output/binary_writer.hpp>
14912// __ _____ _____ _____
14913// __| | __| | | | JSON for Modern C++
14914// | | |__ | | | | | | version 3.11.3
14915// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14916//
14917// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14918// SPDX-License-Identifier: MIT
14919
14920
14921
14922#include <algorithm> // reverse
14923#include <array> // array
14924#include <map> // map
14925#include <cmath> // isnan, isinf
14926#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14927#include <cstring> // memcpy
14928#include <limits> // numeric_limits
14929#include <string> // string
14930#include <utility> // move
14931#include <vector> // vector
14932
14933// #include <nlohmann/detail/input/binary_reader.hpp>
14934
14935// #include <nlohmann/detail/macro_scope.hpp>
14936
14937// #include <nlohmann/detail/output/output_adapters.hpp>
14938// __ _____ _____ _____
14939// __| | __| | | | JSON for Modern C++
14940// | | |__ | | | | | | version 3.11.3
14941// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14942//
14943// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14944// SPDX-License-Identifier: MIT
14945
14946
14947
14948#include <algorithm> // copy
14949#include <cstddef> // size_t
14950#include <iterator> // back_inserter
14951#include <memory> // shared_ptr, make_shared
14952#include <string> // basic_string
14953#include <vector> // vector
14954
14955#ifndef JSON_NO_IO
14956 #include <ios> // streamsize
14957 #include <ostream> // basic_ostream
14958#endif // JSON_NO_IO
14959
14960// #include <nlohmann/detail/macro_scope.hpp>
14961
14962
14964namespace detail
14965{
14966
14968template<typename CharType> struct output_adapter_protocol
14969{
14970 virtual void write_character(CharType c) = 0;
14971 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14972 virtual ~output_adapter_protocol() = default;
14973
14978 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14979};
14980
14982template<typename CharType>
14983using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14984
14986template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14988{
14989 public:
14990 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14991 : v(vec)
14992 {}
14993
14994 void write_character(CharType c) override
14995 {
14996 v.push_back(c);
14997 }
14998
15000 void write_characters(const CharType* s, std::size_t length) override
15001 {
15002 v.insert(v.end(), s, s + length);
15003 }
15004
15005 private:
15006 std::vector<CharType, AllocatorType>& v;
15007};
15008
15009#ifndef JSON_NO_IO
15011template<typename CharType>
15013{
15014 public:
15015 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15016 : stream(s)
15017 {}
15018
15019 void write_character(CharType c) override
15020 {
15021 stream.put(c);
15022 }
15023
15025 void write_characters(const CharType* s, std::size_t length) override
15026 {
15027 stream.write(s, static_cast<std::streamsize>(length));
15028 }
15029
15030 private:
15031 std::basic_ostream<CharType>& stream;
15032};
15033#endif // JSON_NO_IO
15034
15036template<typename CharType, typename StringType = std::basic_string<CharType>>
15038{
15039 public:
15040 explicit output_string_adapter(StringType& s) noexcept
15041 : str(s)
15042 {}
15043
15044 void write_character(CharType c) override
15045 {
15046 str.push_back(c);
15047 }
15048
15050 void write_characters(const CharType* s, std::size_t length) override
15051 {
15052 str.append(s, length);
15053 }
15054
15055 private:
15056 StringType& str;
15057};
15058
15059template<typename CharType, typename StringType = std::basic_string<CharType>>
15061{
15062 public:
15063 template<typename AllocatorType = std::allocator<CharType>>
15064 output_adapter(std::vector<CharType, AllocatorType>& vec)
15065 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15066
15067#ifndef JSON_NO_IO
15068 output_adapter(std::basic_ostream<CharType>& s)
15069 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15070#endif // JSON_NO_IO
15071
15072 output_adapter(StringType& s)
15073 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15074
15076 {
15077 return oa;
15078 }
15079
15080 private:
15081 output_adapter_t<CharType> oa = nullptr;
15082};
15083
15084} // namespace detail
15086
15087// #include <nlohmann/detail/string_concat.hpp>
15088
15089
15091namespace detail
15092{
15093
15095// binary writer //
15097
15101template<typename BasicJsonType, typename CharType>
15103{
15104 using string_t = typename BasicJsonType::string_t;
15105 using binary_t = typename BasicJsonType::binary_t;
15106 using number_float_t = typename BasicJsonType::number_float_t;
15107
15108 public:
15114 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15115 {
15116 JSON_ASSERT(oa);
15117 }
15118
15123 void write_bson(const BasicJsonType& j)
15124 {
15125 switch (j.type())
15126 {
15127 case value_t::object:
15128 {
15129 write_bson_object(*j.m_data.m_value.object);
15130 break;
15131 }
15132
15133 case value_t::null:
15134 case value_t::array:
15135 case value_t::string:
15136 case value_t::boolean:
15137 case value_t::number_integer:
15138 case value_t::number_unsigned:
15139 case value_t::number_float:
15140 case value_t::binary:
15141 case value_t::discarded:
15142 default:
15143 {
15144 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15145 }
15146 }
15147 }
15148
15152 void write_cbor(const BasicJsonType& j)
15153 {
15154 switch (j.type())
15155 {
15156 case value_t::null:
15157 {
15158 oa->write_character(to_char_type(0xF6));
15159 break;
15160 }
15161
15162 case value_t::boolean:
15163 {
15164 oa->write_character(j.m_data.m_value.boolean
15165 ? to_char_type(0xF5)
15166 : to_char_type(0xF4));
15167 break;
15168 }
15169
15170 case value_t::number_integer:
15171 {
15172 if (j.m_data.m_value.number_integer >= 0)
15173 {
15174 // CBOR does not differentiate between positive signed
15175 // integers and unsigned integers. Therefore, we used the
15176 // code from the value_t::number_unsigned case here.
15177 if (j.m_data.m_value.number_integer <= 0x17)
15178 {
15179 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15180 }
15181 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15182 {
15183 oa->write_character(to_char_type(0x18));
15184 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15185 }
15186 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15187 {
15188 oa->write_character(to_char_type(0x19));
15189 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15190 }
15191 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15192 {
15193 oa->write_character(to_char_type(0x1A));
15194 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15195 }
15196 else
15197 {
15198 oa->write_character(to_char_type(0x1B));
15199 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15200 }
15201 }
15202 else
15203 {
15204 // The conversions below encode the sign in the first
15205 // byte, and the value is converted to a positive number.
15206 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15207 if (j.m_data.m_value.number_integer >= -24)
15208 {
15209 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15210 }
15211 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15212 {
15213 oa->write_character(to_char_type(0x38));
15214 write_number(static_cast<std::uint8_t>(positive_number));
15215 }
15216 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15217 {
15218 oa->write_character(to_char_type(0x39));
15219 write_number(static_cast<std::uint16_t>(positive_number));
15220 }
15221 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15222 {
15223 oa->write_character(to_char_type(0x3A));
15224 write_number(static_cast<std::uint32_t>(positive_number));
15225 }
15226 else
15227 {
15228 oa->write_character(to_char_type(0x3B));
15229 write_number(static_cast<std::uint64_t>(positive_number));
15230 }
15231 }
15232 break;
15233 }
15234
15235 case value_t::number_unsigned:
15236 {
15237 if (j.m_data.m_value.number_unsigned <= 0x17)
15238 {
15239 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15240 }
15241 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15242 {
15243 oa->write_character(to_char_type(0x18));
15244 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15245 }
15246 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15247 {
15248 oa->write_character(to_char_type(0x19));
15249 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15250 }
15251 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15252 {
15253 oa->write_character(to_char_type(0x1A));
15254 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15255 }
15256 else
15257 {
15258 oa->write_character(to_char_type(0x1B));
15259 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15260 }
15261 break;
15262 }
15263
15264 case value_t::number_float:
15265 {
15266 if (std::isnan(j.m_data.m_value.number_float))
15267 {
15268 // NaN is 0xf97e00 in CBOR
15269 oa->write_character(to_char_type(0xF9));
15270 oa->write_character(to_char_type(0x7E));
15271 oa->write_character(to_char_type(0x00));
15272 }
15273 else if (std::isinf(j.m_data.m_value.number_float))
15274 {
15275 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15276 oa->write_character(to_char_type(0xf9));
15277 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15278 oa->write_character(to_char_type(0x00));
15279 }
15280 else
15281 {
15282 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15283 }
15284 break;
15285 }
15286
15287 case value_t::string:
15288 {
15289 // step 1: write control byte and the string length
15290 const auto N = j.m_data.m_value.string->size();
15291 if (N <= 0x17)
15292 {
15293 write_number(static_cast<std::uint8_t>(0x60 + N));
15294 }
15295 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15296 {
15297 oa->write_character(to_char_type(0x78));
15298 write_number(static_cast<std::uint8_t>(N));
15299 }
15300 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15301 {
15302 oa->write_character(to_char_type(0x79));
15303 write_number(static_cast<std::uint16_t>(N));
15304 }
15305 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15306 {
15307 oa->write_character(to_char_type(0x7A));
15308 write_number(static_cast<std::uint32_t>(N));
15309 }
15310 // LCOV_EXCL_START
15311 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15312 {
15313 oa->write_character(to_char_type(0x7B));
15314 write_number(static_cast<std::uint64_t>(N));
15315 }
15316 // LCOV_EXCL_STOP
15317
15318 // step 2: write the string
15319 oa->write_characters(
15320 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15321 j.m_data.m_value.string->size());
15322 break;
15323 }
15324
15325 case value_t::array:
15326 {
15327 // step 1: write control byte and the array size
15328 const auto N = j.m_data.m_value.array->size();
15329 if (N <= 0x17)
15330 {
15331 write_number(static_cast<std::uint8_t>(0x80 + N));
15332 }
15333 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15334 {
15335 oa->write_character(to_char_type(0x98));
15336 write_number(static_cast<std::uint8_t>(N));
15337 }
15338 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15339 {
15340 oa->write_character(to_char_type(0x99));
15341 write_number(static_cast<std::uint16_t>(N));
15342 }
15343 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15344 {
15345 oa->write_character(to_char_type(0x9A));
15346 write_number(static_cast<std::uint32_t>(N));
15347 }
15348 // LCOV_EXCL_START
15349 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15350 {
15351 oa->write_character(to_char_type(0x9B));
15352 write_number(static_cast<std::uint64_t>(N));
15353 }
15354 // LCOV_EXCL_STOP
15355
15356 // step 2: write each element
15357 for (const auto& el : *j.m_data.m_value.array)
15358 {
15359 write_cbor(el);
15360 }
15361 break;
15362 }
15363
15364 case value_t::binary:
15365 {
15366 if (j.m_data.m_value.binary->has_subtype())
15367 {
15368 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15369 {
15370 write_number(static_cast<std::uint8_t>(0xd8));
15371 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15372 }
15373 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15374 {
15375 write_number(static_cast<std::uint8_t>(0xd9));
15376 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15377 }
15378 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15379 {
15380 write_number(static_cast<std::uint8_t>(0xda));
15381 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15382 }
15383 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15384 {
15385 write_number(static_cast<std::uint8_t>(0xdb));
15386 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15387 }
15388 }
15389
15390 // step 1: write control byte and the binary array size
15391 const auto N = j.m_data.m_value.binary->size();
15392 if (N <= 0x17)
15393 {
15394 write_number(static_cast<std::uint8_t>(0x40 + N));
15395 }
15396 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15397 {
15398 oa->write_character(to_char_type(0x58));
15399 write_number(static_cast<std::uint8_t>(N));
15400 }
15401 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15402 {
15403 oa->write_character(to_char_type(0x59));
15404 write_number(static_cast<std::uint16_t>(N));
15405 }
15406 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15407 {
15408 oa->write_character(to_char_type(0x5A));
15409 write_number(static_cast<std::uint32_t>(N));
15410 }
15411 // LCOV_EXCL_START
15412 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15413 {
15414 oa->write_character(to_char_type(0x5B));
15415 write_number(static_cast<std::uint64_t>(N));
15416 }
15417 // LCOV_EXCL_STOP
15418
15419 // step 2: write each element
15420 oa->write_characters(
15421 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15422 N);
15423
15424 break;
15425 }
15426
15427 case value_t::object:
15428 {
15429 // step 1: write control byte and the object size
15430 const auto N = j.m_data.m_value.object->size();
15431 if (N <= 0x17)
15432 {
15433 write_number(static_cast<std::uint8_t>(0xA0 + N));
15434 }
15435 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15436 {
15437 oa->write_character(to_char_type(0xB8));
15438 write_number(static_cast<std::uint8_t>(N));
15439 }
15440 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15441 {
15442 oa->write_character(to_char_type(0xB9));
15443 write_number(static_cast<std::uint16_t>(N));
15444 }
15445 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15446 {
15447 oa->write_character(to_char_type(0xBA));
15448 write_number(static_cast<std::uint32_t>(N));
15449 }
15450 // LCOV_EXCL_START
15451 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15452 {
15453 oa->write_character(to_char_type(0xBB));
15454 write_number(static_cast<std::uint64_t>(N));
15455 }
15456 // LCOV_EXCL_STOP
15457
15458 // step 2: write each element
15459 for (const auto& el : *j.m_data.m_value.object)
15460 {
15461 write_cbor(el.first);
15462 write_cbor(el.second);
15463 }
15464 break;
15465 }
15466
15467 case value_t::discarded:
15468 default:
15469 break;
15470 }
15471 }
15472
15476 void write_msgpack(const BasicJsonType& j)
15477 {
15478 switch (j.type())
15479 {
15480 case value_t::null: // nil
15481 {
15482 oa->write_character(to_char_type(0xC0));
15483 break;
15484 }
15485
15486 case value_t::boolean: // true and false
15487 {
15488 oa->write_character(j.m_data.m_value.boolean
15489 ? to_char_type(0xC3)
15490 : to_char_type(0xC2));
15491 break;
15492 }
15493
15494 case value_t::number_integer:
15495 {
15496 if (j.m_data.m_value.number_integer >= 0)
15497 {
15498 // MessagePack does not differentiate between positive
15499 // signed integers and unsigned integers. Therefore, we used
15500 // the code from the value_t::number_unsigned case here.
15501 if (j.m_data.m_value.number_unsigned < 128)
15502 {
15503 // positive fixnum
15504 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15505 }
15506 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15507 {
15508 // uint 8
15509 oa->write_character(to_char_type(0xCC));
15510 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15511 }
15512 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15513 {
15514 // uint 16
15515 oa->write_character(to_char_type(0xCD));
15516 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15517 }
15518 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15519 {
15520 // uint 32
15521 oa->write_character(to_char_type(0xCE));
15522 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15523 }
15524 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15525 {
15526 // uint 64
15527 oa->write_character(to_char_type(0xCF));
15528 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15529 }
15530 }
15531 else
15532 {
15533 if (j.m_data.m_value.number_integer >= -32)
15534 {
15535 // negative fixnum
15536 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15537 }
15538 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15539 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15540 {
15541 // int 8
15542 oa->write_character(to_char_type(0xD0));
15543 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15544 }
15545 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15546 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15547 {
15548 // int 16
15549 oa->write_character(to_char_type(0xD1));
15550 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15551 }
15552 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15553 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15554 {
15555 // int 32
15556 oa->write_character(to_char_type(0xD2));
15557 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15558 }
15559 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15560 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15561 {
15562 // int 64
15563 oa->write_character(to_char_type(0xD3));
15564 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15565 }
15566 }
15567 break;
15568 }
15569
15570 case value_t::number_unsigned:
15571 {
15572 if (j.m_data.m_value.number_unsigned < 128)
15573 {
15574 // positive fixnum
15575 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15576 }
15577 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15578 {
15579 // uint 8
15580 oa->write_character(to_char_type(0xCC));
15581 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15582 }
15583 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15584 {
15585 // uint 16
15586 oa->write_character(to_char_type(0xCD));
15587 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15588 }
15589 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15590 {
15591 // uint 32
15592 oa->write_character(to_char_type(0xCE));
15593 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15594 }
15595 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15596 {
15597 // uint 64
15598 oa->write_character(to_char_type(0xCF));
15599 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15600 }
15601 break;
15602 }
15603
15604 case value_t::number_float:
15605 {
15606 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15607 break;
15608 }
15609
15610 case value_t::string:
15611 {
15612 // step 1: write control byte and the string length
15613 const auto N = j.m_data.m_value.string->size();
15614 if (N <= 31)
15615 {
15616 // fixstr
15617 write_number(static_cast<std::uint8_t>(0xA0 | N));
15618 }
15619 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15620 {
15621 // str 8
15622 oa->write_character(to_char_type(0xD9));
15623 write_number(static_cast<std::uint8_t>(N));
15624 }
15625 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15626 {
15627 // str 16
15628 oa->write_character(to_char_type(0xDA));
15629 write_number(static_cast<std::uint16_t>(N));
15630 }
15631 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15632 {
15633 // str 32
15634 oa->write_character(to_char_type(0xDB));
15635 write_number(static_cast<std::uint32_t>(N));
15636 }
15637
15638 // step 2: write the string
15639 oa->write_characters(
15640 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15641 j.m_data.m_value.string->size());
15642 break;
15643 }
15644
15645 case value_t::array:
15646 {
15647 // step 1: write control byte and the array size
15648 const auto N = j.m_data.m_value.array->size();
15649 if (N <= 15)
15650 {
15651 // fixarray
15652 write_number(static_cast<std::uint8_t>(0x90 | N));
15653 }
15654 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15655 {
15656 // array 16
15657 oa->write_character(to_char_type(0xDC));
15658 write_number(static_cast<std::uint16_t>(N));
15659 }
15660 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15661 {
15662 // array 32
15663 oa->write_character(to_char_type(0xDD));
15664 write_number(static_cast<std::uint32_t>(N));
15665 }
15666
15667 // step 2: write each element
15668 for (const auto& el : *j.m_data.m_value.array)
15669 {
15670 write_msgpack(el);
15671 }
15672 break;
15673 }
15674
15675 case value_t::binary:
15676 {
15677 // step 0: determine if the binary type has a set subtype to
15678 // determine whether or not to use the ext or fixext types
15679 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15680
15681 // step 1: write control byte and the byte string length
15682 const auto N = j.m_data.m_value.binary->size();
15683 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15684 {
15685 std::uint8_t output_type{};
15686 bool fixed = true;
15687 if (use_ext)
15688 {
15689 switch (N)
15690 {
15691 case 1:
15692 output_type = 0xD4; // fixext 1
15693 break;
15694 case 2:
15695 output_type = 0xD5; // fixext 2
15696 break;
15697 case 4:
15698 output_type = 0xD6; // fixext 4
15699 break;
15700 case 8:
15701 output_type = 0xD7; // fixext 8
15702 break;
15703 case 16:
15704 output_type = 0xD8; // fixext 16
15705 break;
15706 default:
15707 output_type = 0xC7; // ext 8
15708 fixed = false;
15709 break;
15710 }
15711
15712 }
15713 else
15714 {
15715 output_type = 0xC4; // bin 8
15716 fixed = false;
15717 }
15718
15719 oa->write_character(to_char_type(output_type));
15720 if (!fixed)
15721 {
15722 write_number(static_cast<std::uint8_t>(N));
15723 }
15724 }
15725 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15726 {
15727 const std::uint8_t output_type = use_ext
15728 ? 0xC8 // ext 16
15729 : 0xC5; // bin 16
15730
15731 oa->write_character(to_char_type(output_type));
15732 write_number(static_cast<std::uint16_t>(N));
15733 }
15734 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15735 {
15736 const std::uint8_t output_type = use_ext
15737 ? 0xC9 // ext 32
15738 : 0xC6; // bin 32
15739
15740 oa->write_character(to_char_type(output_type));
15741 write_number(static_cast<std::uint32_t>(N));
15742 }
15743
15744 // step 1.5: if this is an ext type, write the subtype
15745 if (use_ext)
15746 {
15747 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15748 }
15749
15750 // step 2: write the byte string
15751 oa->write_characters(
15752 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15753 N);
15754
15755 break;
15756 }
15757
15758 case value_t::object:
15759 {
15760 // step 1: write control byte and the object size
15761 const auto N = j.m_data.m_value.object->size();
15762 if (N <= 15)
15763 {
15764 // fixmap
15765 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15766 }
15767 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15768 {
15769 // map 16
15770 oa->write_character(to_char_type(0xDE));
15771 write_number(static_cast<std::uint16_t>(N));
15772 }
15773 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15774 {
15775 // map 32
15776 oa->write_character(to_char_type(0xDF));
15777 write_number(static_cast<std::uint32_t>(N));
15778 }
15779
15780 // step 2: write each element
15781 for (const auto& el : *j.m_data.m_value.object)
15782 {
15783 write_msgpack(el.first);
15784 write_msgpack(el.second);
15785 }
15786 break;
15787 }
15788
15789 case value_t::discarded:
15790 default:
15791 break;
15792 }
15793 }
15794
15802 void write_ubjson(const BasicJsonType& j, const bool use_count,
15803 const bool use_type, const bool add_prefix = true,
15804 const bool use_bjdata = false)
15805 {
15806 switch (j.type())
15807 {
15808 case value_t::null:
15809 {
15810 if (add_prefix)
15811 {
15812 oa->write_character(to_char_type('Z'));
15813 }
15814 break;
15815 }
15816
15817 case value_t::boolean:
15818 {
15819 if (add_prefix)
15820 {
15821 oa->write_character(j.m_data.m_value.boolean
15822 ? to_char_type('T')
15823 : to_char_type('F'));
15824 }
15825 break;
15826 }
15827
15828 case value_t::number_integer:
15829 {
15830 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15831 break;
15832 }
15833
15834 case value_t::number_unsigned:
15835 {
15836 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15837 break;
15838 }
15839
15840 case value_t::number_float:
15841 {
15842 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15843 break;
15844 }
15845
15846 case value_t::string:
15847 {
15848 if (add_prefix)
15849 {
15850 oa->write_character(to_char_type('S'));
15851 }
15852 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15853 oa->write_characters(
15854 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15855 j.m_data.m_value.string->size());
15856 break;
15857 }
15858
15859 case value_t::array:
15860 {
15861 if (add_prefix)
15862 {
15863 oa->write_character(to_char_type('['));
15864 }
15865
15866 bool prefix_required = true;
15867 if (use_type && !j.m_data.m_value.array->empty())
15868 {
15869 JSON_ASSERT(use_count);
15870 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15871 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15872 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15873 {
15874 return ubjson_prefix(v, use_bjdata) == first_prefix;
15875 });
15876
15877 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15878
15879 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15880 {
15881 prefix_required = false;
15882 oa->write_character(to_char_type('$'));
15883 oa->write_character(first_prefix);
15884 }
15885 }
15886
15887 if (use_count)
15888 {
15889 oa->write_character(to_char_type('#'));
15890 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15891 }
15892
15893 for (const auto& el : *j.m_data.m_value.array)
15894 {
15895 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15896 }
15897
15898 if (!use_count)
15899 {
15900 oa->write_character(to_char_type(']'));
15901 }
15902
15903 break;
15904 }
15905
15906 case value_t::binary:
15907 {
15908 if (add_prefix)
15909 {
15910 oa->write_character(to_char_type('['));
15911 }
15912
15913 if (use_type && !j.m_data.m_value.binary->empty())
15914 {
15915 JSON_ASSERT(use_count);
15916 oa->write_character(to_char_type('$'));
15917 oa->write_character('U');
15918 }
15919
15920 if (use_count)
15921 {
15922 oa->write_character(to_char_type('#'));
15923 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15924 }
15925
15926 if (use_type)
15927 {
15928 oa->write_characters(
15929 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15930 j.m_data.m_value.binary->size());
15931 }
15932 else
15933 {
15934 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15935 {
15936 oa->write_character(to_char_type('U'));
15937 oa->write_character(j.m_data.m_value.binary->data()[i]);
15938 }
15939 }
15940
15941 if (!use_count)
15942 {
15943 oa->write_character(to_char_type(']'));
15944 }
15945
15946 break;
15947 }
15948
15949 case value_t::object:
15950 {
15951 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
15952 {
15953 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15954 {
15955 break;
15956 }
15957 }
15958
15959 if (add_prefix)
15960 {
15961 oa->write_character(to_char_type('{'));
15962 }
15963
15964 bool prefix_required = true;
15965 if (use_type && !j.m_data.m_value.object->empty())
15966 {
15967 JSON_ASSERT(use_count);
15968 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15969 const bool same_prefix = std::all_of(j.begin(), j.end(),
15970 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15971 {
15972 return ubjson_prefix(v, use_bjdata) == first_prefix;
15973 });
15974
15975 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15976
15977 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15978 {
15979 prefix_required = false;
15980 oa->write_character(to_char_type('$'));
15981 oa->write_character(first_prefix);
15982 }
15983 }
15984
15985 if (use_count)
15986 {
15987 oa->write_character(to_char_type('#'));
15988 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15989 }
15990
15991 for (const auto& el : *j.m_data.m_value.object)
15992 {
15993 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15994 oa->write_characters(
15995 reinterpret_cast<const CharType*>(el.first.c_str()),
15996 el.first.size());
15997 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15998 }
15999
16000 if (!use_count)
16001 {
16002 oa->write_character(to_char_type('}'));
16003 }
16004
16005 break;
16006 }
16007
16008 case value_t::discarded:
16009 default:
16010 break;
16011 }
16012 }
16013
16014 private:
16016 // BSON //
16018
16023 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16024 {
16025 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16026 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16027 {
16028 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16029 static_cast<void>(j);
16030 }
16031
16032 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16033 }
16034
16038 void write_bson_entry_header(const string_t& name,
16039 const std::uint8_t element_type)
16040 {
16041 oa->write_character(to_char_type(element_type)); // boolean
16042 oa->write_characters(
16043 reinterpret_cast<const CharType*>(name.c_str()),
16044 name.size() + 1u);
16045 }
16046
16050 void write_bson_boolean(const string_t& name,
16051 const bool value)
16052 {
16053 write_bson_entry_header(name, 0x08);
16054 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16055 }
16056
16060 void write_bson_double(const string_t& name,
16061 const double value)
16062 {
16063 write_bson_entry_header(name, 0x01);
16064 write_number<double>(value, true);
16065 }
16066
16070 static std::size_t calc_bson_string_size(const string_t& value)
16071 {
16072 return sizeof(std::int32_t) + value.size() + 1ul;
16073 }
16074
16078 void write_bson_string(const string_t& name,
16079 const string_t& value)
16080 {
16081 write_bson_entry_header(name, 0x02);
16082
16083 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16084 oa->write_characters(
16085 reinterpret_cast<const CharType*>(value.c_str()),
16086 value.size() + 1);
16087 }
16088
16092 void write_bson_null(const string_t& name)
16093 {
16094 write_bson_entry_header(name, 0x0A);
16095 }
16096
16100 static std::size_t calc_bson_integer_size(const std::int64_t value)
16101 {
16102 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16103 ? sizeof(std::int32_t)
16104 : sizeof(std::int64_t);
16105 }
16106
16110 void write_bson_integer(const string_t& name,
16111 const std::int64_t value)
16112 {
16113 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16114 {
16115 write_bson_entry_header(name, 0x10); // int32
16116 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16117 }
16118 else
16119 {
16120 write_bson_entry_header(name, 0x12); // int64
16121 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16122 }
16123 }
16124
16128 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16129 {
16130 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16131 ? sizeof(std::int32_t)
16132 : sizeof(std::int64_t);
16133 }
16134
16138 void write_bson_unsigned(const string_t& name,
16139 const BasicJsonType& j)
16140 {
16141 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16142 {
16143 write_bson_entry_header(name, 0x10 /* int32 */);
16144 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16145 }
16146 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16147 {
16148 write_bson_entry_header(name, 0x12 /* int64 */);
16149 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16150 }
16151 else
16152 {
16153 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16154 }
16155 }
16156
16160 void write_bson_object_entry(const string_t& name,
16161 const typename BasicJsonType::object_t& value)
16162 {
16163 write_bson_entry_header(name, 0x03); // object
16164 write_bson_object(value);
16165 }
16166
16170 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16171 {
16172 std::size_t array_index = 0ul;
16173
16174 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16175 {
16176 return result + calc_bson_element_size(std::to_string(array_index++), el);
16177 });
16178
16179 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16180 }
16181
16185 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16186 {
16187 return sizeof(std::int32_t) + value.size() + 1ul;
16188 }
16189
16193 void write_bson_array(const string_t& name,
16194 const typename BasicJsonType::array_t& value)
16195 {
16196 write_bson_entry_header(name, 0x04); // array
16197 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16198
16199 std::size_t array_index = 0ul;
16200
16201 for (const auto& el : value)
16202 {
16203 write_bson_element(std::to_string(array_index++), el);
16204 }
16205
16206 oa->write_character(to_char_type(0x00));
16207 }
16208
16212 void write_bson_binary(const string_t& name,
16213 const binary_t& value)
16214 {
16215 write_bson_entry_header(name, 0x05);
16216
16217 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16218 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16219
16220 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16221 }
16222
16227 static std::size_t calc_bson_element_size(const string_t& name,
16228 const BasicJsonType& j)
16229 {
16230 const auto header_size = calc_bson_entry_header_size(name, j);
16231 switch (j.type())
16232 {
16233 case value_t::object:
16234 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16235
16236 case value_t::array:
16237 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16238
16239 case value_t::binary:
16240 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16241
16242 case value_t::boolean:
16243 return header_size + 1ul;
16244
16245 case value_t::number_float:
16246 return header_size + 8ul;
16247
16248 case value_t::number_integer:
16249 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16250
16251 case value_t::number_unsigned:
16252 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16253
16254 case value_t::string:
16255 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16256
16257 case value_t::null:
16258 return header_size + 0ul;
16259
16260 // LCOV_EXCL_START
16261 case value_t::discarded:
16262 default:
16263 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16264 return 0ul;
16265 // LCOV_EXCL_STOP
16266 }
16267 }
16268
16275 void write_bson_element(const string_t& name,
16276 const BasicJsonType& j)
16277 {
16278 switch (j.type())
16279 {
16280 case value_t::object:
16281 return write_bson_object_entry(name, *j.m_data.m_value.object);
16282
16283 case value_t::array:
16284 return write_bson_array(name, *j.m_data.m_value.array);
16285
16286 case value_t::binary:
16287 return write_bson_binary(name, *j.m_data.m_value.binary);
16288
16289 case value_t::boolean:
16290 return write_bson_boolean(name, j.m_data.m_value.boolean);
16291
16292 case value_t::number_float:
16293 return write_bson_double(name, j.m_data.m_value.number_float);
16294
16295 case value_t::number_integer:
16296 return write_bson_integer(name, j.m_data.m_value.number_integer);
16297
16298 case value_t::number_unsigned:
16299 return write_bson_unsigned(name, j);
16300
16301 case value_t::string:
16302 return write_bson_string(name, *j.m_data.m_value.string);
16303
16304 case value_t::null:
16305 return write_bson_null(name);
16306
16307 // LCOV_EXCL_START
16308 case value_t::discarded:
16309 default:
16310 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16311 return;
16312 // LCOV_EXCL_STOP
16313 }
16314 }
16315
16322 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16323 {
16324 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16325 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16326 {
16327 return result += calc_bson_element_size(el.first, el.second);
16328 });
16329
16330 return sizeof(std::int32_t) + document_size + 1ul;
16331 }
16332
16337 void write_bson_object(const typename BasicJsonType::object_t& value)
16338 {
16339 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16340
16341 for (const auto& el : value)
16342 {
16343 write_bson_element(el.first, el.second);
16344 }
16345
16346 oa->write_character(to_char_type(0x00));
16347 }
16348
16350 // CBOR //
16352
16353 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16354 {
16355 return to_char_type(0xFA); // Single-Precision Float
16356 }
16357
16358 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16359 {
16360 return to_char_type(0xFB); // Double-Precision Float
16361 }
16362
16364 // MsgPack //
16366
16367 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16368 {
16369 return to_char_type(0xCA); // float 32
16370 }
16371
16372 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16373 {
16374 return to_char_type(0xCB); // float 64
16375 }
16376
16378 // UBJSON //
16380
16381 // UBJSON: write number (floating point)
16382 template<typename NumberType, typename std::enable_if<
16383 std::is_floating_point<NumberType>::value, int>::type = 0>
16384 void write_number_with_ubjson_prefix(const NumberType n,
16385 const bool add_prefix,
16386 const bool use_bjdata)
16387 {
16388 if (add_prefix)
16389 {
16390 oa->write_character(get_ubjson_float_prefix(n));
16391 }
16392 write_number(n, use_bjdata);
16393 }
16394
16395 // UBJSON: write number (unsigned integer)
16396 template<typename NumberType, typename std::enable_if<
16397 std::is_unsigned<NumberType>::value, int>::type = 0>
16398 void write_number_with_ubjson_prefix(const NumberType n,
16399 const bool add_prefix,
16400 const bool use_bjdata)
16401 {
16402 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16403 {
16404 if (add_prefix)
16405 {
16406 oa->write_character(to_char_type('i')); // int8
16407 }
16408 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16409 }
16410 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16411 {
16412 if (add_prefix)
16413 {
16414 oa->write_character(to_char_type('U')); // uint8
16415 }
16416 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16417 }
16418 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16419 {
16420 if (add_prefix)
16421 {
16422 oa->write_character(to_char_type('I')); // int16
16423 }
16424 write_number(static_cast<std::int16_t>(n), use_bjdata);
16425 }
16426 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16427 {
16428 if (add_prefix)
16429 {
16430 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16431 }
16432 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16433 }
16434 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16435 {
16436 if (add_prefix)
16437 {
16438 oa->write_character(to_char_type('l')); // int32
16439 }
16440 write_number(static_cast<std::int32_t>(n), use_bjdata);
16441 }
16442 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16443 {
16444 if (add_prefix)
16445 {
16446 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16447 }
16448 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16449 }
16450 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16451 {
16452 if (add_prefix)
16453 {
16454 oa->write_character(to_char_type('L')); // int64
16455 }
16456 write_number(static_cast<std::int64_t>(n), use_bjdata);
16457 }
16458 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16459 {
16460 if (add_prefix)
16461 {
16462 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16463 }
16464 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16465 }
16466 else
16467 {
16468 if (add_prefix)
16469 {
16470 oa->write_character(to_char_type('H')); // high-precision number
16471 }
16472
16473 const auto number = BasicJsonType(n).dump();
16474 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16475 for (std::size_t i = 0; i < number.size(); ++i)
16476 {
16477 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16478 }
16479 }
16480 }
16481
16482 // UBJSON: write number (signed integer)
16483 template < typename NumberType, typename std::enable_if <
16484 std::is_signed<NumberType>::value&&
16485 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16486 void write_number_with_ubjson_prefix(const NumberType n,
16487 const bool add_prefix,
16488 const bool use_bjdata)
16489 {
16490 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16491 {
16492 if (add_prefix)
16493 {
16494 oa->write_character(to_char_type('i')); // int8
16495 }
16496 write_number(static_cast<std::int8_t>(n), use_bjdata);
16497 }
16498 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16499 {
16500 if (add_prefix)
16501 {
16502 oa->write_character(to_char_type('U')); // uint8
16503 }
16504 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16505 }
16506 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16507 {
16508 if (add_prefix)
16509 {
16510 oa->write_character(to_char_type('I')); // int16
16511 }
16512 write_number(static_cast<std::int16_t>(n), use_bjdata);
16513 }
16514 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16515 {
16516 if (add_prefix)
16517 {
16518 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16519 }
16520 write_number(static_cast<uint16_t>(n), use_bjdata);
16521 }
16522 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16523 {
16524 if (add_prefix)
16525 {
16526 oa->write_character(to_char_type('l')); // int32
16527 }
16528 write_number(static_cast<std::int32_t>(n), use_bjdata);
16529 }
16530 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16531 {
16532 if (add_prefix)
16533 {
16534 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16535 }
16536 write_number(static_cast<uint32_t>(n), use_bjdata);
16537 }
16538 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16539 {
16540 if (add_prefix)
16541 {
16542 oa->write_character(to_char_type('L')); // int64
16543 }
16544 write_number(static_cast<std::int64_t>(n), use_bjdata);
16545 }
16546 // LCOV_EXCL_START
16547 else
16548 {
16549 if (add_prefix)
16550 {
16551 oa->write_character(to_char_type('H')); // high-precision number
16552 }
16553
16554 const auto number = BasicJsonType(n).dump();
16555 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16556 for (std::size_t i = 0; i < number.size(); ++i)
16557 {
16558 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16559 }
16560 }
16561 // LCOV_EXCL_STOP
16562 }
16563
16567 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16568 {
16569 switch (j.type())
16570 {
16571 case value_t::null:
16572 return 'Z';
16573
16574 case value_t::boolean:
16575 return j.m_data.m_value.boolean ? 'T' : 'F';
16576
16577 case value_t::number_integer:
16578 {
16579 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16580 {
16581 return 'i';
16582 }
16583 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16584 {
16585 return 'U';
16586 }
16587 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16588 {
16589 return 'I';
16590 }
16591 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16592 {
16593 return 'u';
16594 }
16595 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16596 {
16597 return 'l';
16598 }
16599 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16600 {
16601 return 'm';
16602 }
16603 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16604 {
16605 return 'L';
16606 }
16607 // anything else is treated as high-precision number
16608 return 'H'; // LCOV_EXCL_LINE
16609 }
16610
16611 case value_t::number_unsigned:
16612 {
16613 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16614 {
16615 return 'i';
16616 }
16617 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16618 {
16619 return 'U';
16620 }
16621 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16622 {
16623 return 'I';
16624 }
16625 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16626 {
16627 return 'u';
16628 }
16629 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16630 {
16631 return 'l';
16632 }
16633 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16634 {
16635 return 'm';
16636 }
16637 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16638 {
16639 return 'L';
16640 }
16641 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16642 {
16643 return 'M';
16644 }
16645 // anything else is treated as high-precision number
16646 return 'H'; // LCOV_EXCL_LINE
16647 }
16648
16649 case value_t::number_float:
16650 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16651
16652 case value_t::string:
16653 return 'S';
16654
16655 case value_t::array: // fallthrough
16656 case value_t::binary:
16657 return '[';
16658
16659 case value_t::object:
16660 return '{';
16661
16662 case value_t::discarded:
16663 default: // discarded values
16664 return 'N';
16665 }
16666 }
16667
16668 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16669 {
16670 return 'd'; // float 32
16671 }
16672
16673 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16674 {
16675 return 'D'; // float 64
16676 }
16677
16681 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16682 {
16683 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16684 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16685 };
16686
16687 string_t key = "_ArrayType_";
16688 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16689 if (it == bjdtype.end())
16690 {
16691 return true;
16692 }
16693 CharType dtype = it->second;
16694
16695 key = "_ArraySize_";
16696 std::size_t len = (value.at(key).empty() ? 0 : 1);
16697 for (const auto& el : value.at(key))
16698 {
16699 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16700 }
16701
16702 key = "_ArrayData_";
16703 if (value.at(key).size() != len)
16704 {
16705 return true;
16706 }
16707
16708 oa->write_character('[');
16709 oa->write_character('$');
16710 oa->write_character(dtype);
16711 oa->write_character('#');
16712
16713 key = "_ArraySize_";
16714 write_ubjson(value.at(key), use_count, use_type, true, true);
16715
16716 key = "_ArrayData_";
16717 if (dtype == 'U' || dtype == 'C')
16718 {
16719 for (const auto& el : value.at(key))
16720 {
16721 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16722 }
16723 }
16724 else if (dtype == 'i')
16725 {
16726 for (const auto& el : value.at(key))
16727 {
16728 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16729 }
16730 }
16731 else if (dtype == 'u')
16732 {
16733 for (const auto& el : value.at(key))
16734 {
16735 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16736 }
16737 }
16738 else if (dtype == 'I')
16739 {
16740 for (const auto& el : value.at(key))
16741 {
16742 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16743 }
16744 }
16745 else if (dtype == 'm')
16746 {
16747 for (const auto& el : value.at(key))
16748 {
16749 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16750 }
16751 }
16752 else if (dtype == 'l')
16753 {
16754 for (const auto& el : value.at(key))
16755 {
16756 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16757 }
16758 }
16759 else if (dtype == 'M')
16760 {
16761 for (const auto& el : value.at(key))
16762 {
16763 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16764 }
16765 }
16766 else if (dtype == 'L')
16767 {
16768 for (const auto& el : value.at(key))
16769 {
16770 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16771 }
16772 }
16773 else if (dtype == 'd')
16774 {
16775 for (const auto& el : value.at(key))
16776 {
16777 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16778 }
16779 }
16780 else if (dtype == 'D')
16781 {
16782 for (const auto& el : value.at(key))
16783 {
16784 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16785 }
16786 }
16787 return false;
16788 }
16789
16791 // Utility functions //
16793
16794 /*
16795 @brief write a number to output input
16796 @param[in] n number of type @a NumberType
16797 @param[in] OutputIsLittleEndian Set to true if output data is
16798 required to be little endian
16799 @tparam NumberType the type of the number
16800
16801 @note This function needs to respect the system's endianness, because bytes
16802 in CBOR, MessagePack, and UBJSON are stored in network order (big
16803 endian) and therefore need reordering on little endian systems.
16804 On the other hand, BSON and BJData use little endian and should reorder
16805 on big endian systems.
16806 */
16807 template<typename NumberType>
16808 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16809 {
16810 // step 1: write number to array of length NumberType
16811 std::array<CharType, sizeof(NumberType)> vec{};
16812 std::memcpy(vec.data(), &n, sizeof(NumberType));
16813
16814 // step 2: write array to output (with possible reordering)
16815 if (is_little_endian != OutputIsLittleEndian)
16816 {
16817 // reverse byte order prior to conversion if necessary
16818 std::reverse(vec.begin(), vec.end());
16819 }
16820
16821 oa->write_characters(vec.data(), sizeof(NumberType));
16822 }
16823
16824 void write_compact_float(const number_float_t n, detail::input_format_t format)
16825 {
16826#ifdef __GNUC__
16827#pragma GCC diagnostic push
16828#pragma GCC diagnostic ignored "-Wfloat-equal"
16829#endif
16830 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16831 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16832 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16833 {
16834 oa->write_character(format == detail::input_format_t::cbor
16835 ? get_cbor_float_prefix(static_cast<float>(n))
16836 : get_msgpack_float_prefix(static_cast<float>(n)));
16837 write_number(static_cast<float>(n));
16838 }
16839 else
16840 {
16841 oa->write_character(format == detail::input_format_t::cbor
16842 ? get_cbor_float_prefix(n)
16843 : get_msgpack_float_prefix(n));
16844 write_number(n);
16845 }
16846#ifdef __GNUC__
16847#pragma GCC diagnostic pop
16848#endif
16849 }
16850
16851 public:
16852 // The following to_char_type functions are implement the conversion
16853 // between uint8_t and CharType. In case CharType is not unsigned,
16854 // such a conversion is required to allow values greater than 128.
16855 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16856 template < typename C = CharType,
16857 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16858 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16859 {
16860 return *reinterpret_cast<char*>(&x);
16861 }
16862
16863 template < typename C = CharType,
16864 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16865 static CharType to_char_type(std::uint8_t x) noexcept
16866 {
16867 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16868 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16869 CharType result;
16870 std::memcpy(&result, &x, sizeof(x));
16871 return result;
16872 }
16873
16874 template<typename C = CharType,
16876 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16877 {
16878 return x;
16879 }
16880
16881 template < typename InputCharType, typename C = CharType,
16882 enable_if_t <
16883 std::is_signed<C>::value &&
16884 std::is_signed<char>::value &&
16885 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16886 > * = nullptr >
16887 static constexpr CharType to_char_type(InputCharType x) noexcept
16888 {
16889 return x;
16890 }
16891
16892 private:
16894 const bool is_little_endian = little_endianness();
16895
16897 output_adapter_t<CharType> oa = nullptr;
16898};
16899
16900} // namespace detail
16902
16903// #include <nlohmann/detail/output/output_adapters.hpp>
16904
16905// #include <nlohmann/detail/output/serializer.hpp>
16906// __ _____ _____ _____
16907// __| | __| | | | JSON for Modern C++
16908// | | |__ | | | | | | version 3.11.3
16909// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16910//
16911// SPDX-FileCopyrightText: 2008-2009 Bj枚rn Hoehrmann <bjoern@hoehrmann.de>
16912// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16913// SPDX-License-Identifier: MIT
16914
16915
16916
16917#include <algorithm> // reverse, remove, fill, find, none_of
16918#include <array> // array
16919#include <clocale> // localeconv, lconv
16920#include <cmath> // labs, isfinite, isnan, signbit
16921#include <cstddef> // size_t, ptrdiff_t
16922#include <cstdint> // uint8_t
16923#include <cstdio> // snprintf
16924#include <limits> // numeric_limits
16925#include <string> // string, char_traits
16926#include <iomanip> // setfill, setw
16927#include <type_traits> // is_same
16928#include <utility> // move
16929
16930// #include <nlohmann/detail/conversions/to_chars.hpp>
16931// __ _____ _____ _____
16932// __| | __| | | | JSON for Modern C++
16933// | | |__ | | | | | | version 3.11.3
16934// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16935//
16936// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16937// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16938// SPDX-License-Identifier: MIT
16939
16940
16941
16942#include <array> // array
16943#include <cmath> // signbit, isfinite
16944#include <cstdint> // intN_t, uintN_t
16945#include <cstring> // memcpy, memmove
16946#include <limits> // numeric_limits
16947#include <type_traits> // conditional
16948
16949// #include <nlohmann/detail/macro_scope.hpp>
16950
16951
16953namespace detail
16954{
16955
16975namespace dtoa_impl
16976{
16977
16978template<typename Target, typename Source>
16979Target reinterpret_bits(const Source source)
16980{
16981 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16982
16983 Target target;
16984 std::memcpy(&target, &source, sizeof(Source));
16985 return target;
16986}
16987
16988struct diyfp // f * 2^e
16989{
16990 static constexpr int kPrecision = 64; // = q
16991
16992 std::uint64_t f = 0;
16993 int e = 0;
16994
16995 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16996
17001 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17002 {
17003 JSON_ASSERT(x.e == y.e);
17004 JSON_ASSERT(x.f >= y.f);
17005
17006 return {x.f - y.f, x.e};
17007 }
17008
17013 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17014 {
17015 static_assert(kPrecision == 64, "internal error");
17016
17017 // Computes:
17018 // f = round((x.f * y.f) / 2^q)
17019 // e = x.e + y.e + q
17020
17021 // Emulate the 64-bit * 64-bit multiplication:
17022 //
17023 // p = u * v
17024 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17025 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17026 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17027 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17028 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17029 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17030 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17031 //
17032 // (Since Q might be larger than 2^32 - 1)
17033 //
17034 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17035 //
17036 // (Q_hi + H does not overflow a 64-bit int)
17037 //
17038 // = p_lo + 2^64 p_hi
17039
17040 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17041 const std::uint64_t u_hi = x.f >> 32u;
17042 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17043 const std::uint64_t v_hi = y.f >> 32u;
17044
17045 const std::uint64_t p0 = u_lo * v_lo;
17046 const std::uint64_t p1 = u_lo * v_hi;
17047 const std::uint64_t p2 = u_hi * v_lo;
17048 const std::uint64_t p3 = u_hi * v_hi;
17049
17050 const std::uint64_t p0_hi = p0 >> 32u;
17051 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17052 const std::uint64_t p1_hi = p1 >> 32u;
17053 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17054 const std::uint64_t p2_hi = p2 >> 32u;
17055
17056 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17057
17058 // The full product might now be computed as
17059 //
17060 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17061 // p_lo = p0_lo + (Q << 32)
17062 //
17063 // But in this particular case here, the full p_lo is not required.
17064 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17065 // Q_hi + 1 does not overflow).
17066
17067 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17068
17069 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17070
17071 return {h, x.e + y.e + 64};
17072 }
17073
17078 static diyfp normalize(diyfp x) noexcept
17079 {
17080 JSON_ASSERT(x.f != 0);
17081
17082 while ((x.f >> 63u) == 0)
17083 {
17084 x.f <<= 1u;
17085 x.e--;
17086 }
17087
17088 return x;
17089 }
17090
17095 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17096 {
17097 const int delta = x.e - target_exponent;
17098
17099 JSON_ASSERT(delta >= 0);
17100 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17101
17102 return {x.f << delta, target_exponent};
17103 }
17104};
17105
17112
17119template<typename FloatType>
17121{
17122 JSON_ASSERT(std::isfinite(value));
17123 JSON_ASSERT(value > 0);
17124
17125 // Convert the IEEE representation into a diyfp.
17126 //
17127 // If v is denormal:
17128 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17129 // If v is normalized:
17130 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17131
17132 static_assert(std::numeric_limits<FloatType>::is_iec559,
17133 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17134
17135 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17136 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17137 constexpr int kMinExp = 1 - kBias;
17138 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17139
17140 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17141
17142 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17143 const std::uint64_t E = bits >> (kPrecision - 1);
17144 const std::uint64_t F = bits & (kHiddenBit - 1);
17145
17146 const bool is_denormal = E == 0;
17147 const diyfp v = is_denormal
17148 ? diyfp(F, kMinExp)
17149 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17150
17151 // Compute the boundaries m- and m+ of the floating-point value
17152 // v = f * 2^e.
17153 //
17154 // Determine v- and v+, the floating-point predecessor and successor if v,
17155 // respectively.
17156 //
17157 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17158 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17159 //
17160 // v+ = v + 2^e
17161 //
17162 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17163 // between m- and m+ round to v, regardless of how the input rounding
17164 // algorithm breaks ties.
17165 //
17166 // ---+-------------+-------------+-------------+-------------+--- (A)
17167 // v- m- v m+ v+
17168 //
17169 // -----------------+------+------+-------------+-------------+--- (B)
17170 // v- m- v m+ v+
17171
17172 const bool lower_boundary_is_closer = F == 0 && E > 1;
17173 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17174 const diyfp m_minus = lower_boundary_is_closer
17175 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17176 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17177
17178 // Determine the normalized w+ = m+.
17179 const diyfp w_plus = diyfp::normalize(m_plus);
17180
17181 // Determine w- = m- such that e_(w-) = e_(w+).
17182 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17183
17184 return {diyfp::normalize(v), w_minus, w_plus};
17185}
17186
17187// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17188// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17189// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17190//
17191// alpha <= e = e_c + e_w + q <= gamma
17192//
17193// or
17194//
17195// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17196// <= f_c * f_w * 2^gamma
17197//
17198// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17199//
17200// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17201//
17202// or
17203//
17204// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17205//
17206// The choice of (alpha,gamma) determines the size of the table and the form of
17207// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17208// in practice:
17209//
17210// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17211// processed independently: An integral part p1, and a fractional part p2:
17212//
17213// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17214// = (f div 2^-e) + (f mod 2^-e) * 2^e
17215// = p1 + p2 * 2^e
17216//
17217// The conversion of p1 into decimal form requires a series of divisions and
17218// modulos by (a power of) 10. These operations are faster for 32-bit than for
17219// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17220// achieved by choosing
17221//
17222// -e >= 32 or e <= -32 := gamma
17223//
17224// In order to convert the fractional part
17225//
17226// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17227//
17228// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17229// d[-i] are extracted in order:
17230//
17231// (10 * p2) div 2^-e = d[-1]
17232// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17233//
17234// The multiplication by 10 must not overflow. It is sufficient to choose
17235//
17236// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17237//
17238// Since p2 = f mod 2^-e < 2^-e,
17239//
17240// -e <= 60 or e >= -60 := alpha
17241
17242constexpr int kAlpha = -60;
17243constexpr int kGamma = -32;
17244
17245struct cached_power // c = f * 2^e ~= 10^k
17246{
17247 std::uint64_t f;
17248 int e;
17249 int k;
17250};
17251
17260{
17261 // Now
17262 //
17263 // alpha <= e_c + e + q <= gamma (1)
17264 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17265 //
17266 // and since the c's are normalized, 2^(q-1) <= f_c,
17267 //
17268 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17269 // ==> 2^(alpha - e - 1) <= c
17270 //
17271 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17272 //
17273 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17274 // = ceil( (alpha - e - 1) * log_10(2) )
17275 //
17276 // From the paper:
17277 // "In theory the result of the procedure could be wrong since c is rounded,
17278 // and the computation itself is approximated [...]. In practice, however,
17279 // this simple function is sufficient."
17280 //
17281 // For IEEE double precision floating-point numbers converted into
17282 // normalized diyfp's w = f * 2^e, with q = 64,
17283 //
17284 // e >= -1022 (min IEEE exponent)
17285 // -52 (p - 1)
17286 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17287 // -11 (normalize the diyfp)
17288 // = -1137
17289 //
17290 // and
17291 //
17292 // e <= +1023 (max IEEE exponent)
17293 // -52 (p - 1)
17294 // -11 (normalize the diyfp)
17295 // = 960
17296 //
17297 // This binary exponent range [-1137,960] results in a decimal exponent
17298 // range [-307,324]. One does not need to store a cached power for each
17299 // k in this range. For each such k it suffices to find a cached power
17300 // such that the exponent of the product lies in [alpha,gamma].
17301 // This implies that the difference of the decimal exponents of adjacent
17302 // table entries must be less than or equal to
17303 //
17304 // floor( (gamma - alpha) * log_10(2) ) = 8.
17305 //
17306 // (A smaller distance gamma-alpha would require a larger table.)
17307
17308 // NB:
17309 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17310
17311 constexpr int kCachedPowersMinDecExp = -300;
17312 constexpr int kCachedPowersDecStep = 8;
17313
17314 static constexpr std::array<cached_power, 79> kCachedPowers =
17315 {
17316 {
17317 { 0xAB70FE17C79AC6CA, -1060, -300 },
17318 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17319 { 0xBE5691EF416BD60C, -1007, -284 },
17320 { 0x8DD01FAD907FFC3C, -980, -276 },
17321 { 0xD3515C2831559A83, -954, -268 },
17322 { 0x9D71AC8FADA6C9B5, -927, -260 },
17323 { 0xEA9C227723EE8BCB, -901, -252 },
17324 { 0xAECC49914078536D, -874, -244 },
17325 { 0x823C12795DB6CE57, -847, -236 },
17326 { 0xC21094364DFB5637, -821, -228 },
17327 { 0x9096EA6F3848984F, -794, -220 },
17328 { 0xD77485CB25823AC7, -768, -212 },
17329 { 0xA086CFCD97BF97F4, -741, -204 },
17330 { 0xEF340A98172AACE5, -715, -196 },
17331 { 0xB23867FB2A35B28E, -688, -188 },
17332 { 0x84C8D4DFD2C63F3B, -661, -180 },
17333 { 0xC5DD44271AD3CDBA, -635, -172 },
17334 { 0x936B9FCEBB25C996, -608, -164 },
17335 { 0xDBAC6C247D62A584, -582, -156 },
17336 { 0xA3AB66580D5FDAF6, -555, -148 },
17337 { 0xF3E2F893DEC3F126, -529, -140 },
17338 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17339 { 0x87625F056C7C4A8B, -475, -124 },
17340 { 0xC9BCFF6034C13053, -449, -116 },
17341 { 0x964E858C91BA2655, -422, -108 },
17342 { 0xDFF9772470297EBD, -396, -100 },
17343 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17344 { 0xF8A95FCF88747D94, -343, -84 },
17345 { 0xB94470938FA89BCF, -316, -76 },
17346 { 0x8A08F0F8BF0F156B, -289, -68 },
17347 { 0xCDB02555653131B6, -263, -60 },
17348 { 0x993FE2C6D07B7FAC, -236, -52 },
17349 { 0xE45C10C42A2B3B06, -210, -44 },
17350 { 0xAA242499697392D3, -183, -36 },
17351 { 0xFD87B5F28300CA0E, -157, -28 },
17352 { 0xBCE5086492111AEB, -130, -20 },
17353 { 0x8CBCCC096F5088CC, -103, -12 },
17354 { 0xD1B71758E219652C, -77, -4 },
17355 { 0x9C40000000000000, -50, 4 },
17356 { 0xE8D4A51000000000, -24, 12 },
17357 { 0xAD78EBC5AC620000, 3, 20 },
17358 { 0x813F3978F8940984, 30, 28 },
17359 { 0xC097CE7BC90715B3, 56, 36 },
17360 { 0x8F7E32CE7BEA5C70, 83, 44 },
17361 { 0xD5D238A4ABE98068, 109, 52 },
17362 { 0x9F4F2726179A2245, 136, 60 },
17363 { 0xED63A231D4C4FB27, 162, 68 },
17364 { 0xB0DE65388CC8ADA8, 189, 76 },
17365 { 0x83C7088E1AAB65DB, 216, 84 },
17366 { 0xC45D1DF942711D9A, 242, 92 },
17367 { 0x924D692CA61BE758, 269, 100 },
17368 { 0xDA01EE641A708DEA, 295, 108 },
17369 { 0xA26DA3999AEF774A, 322, 116 },
17370 { 0xF209787BB47D6B85, 348, 124 },
17371 { 0xB454E4A179DD1877, 375, 132 },
17372 { 0x865B86925B9BC5C2, 402, 140 },
17373 { 0xC83553C5C8965D3D, 428, 148 },
17374 { 0x952AB45CFA97A0B3, 455, 156 },
17375 { 0xDE469FBD99A05FE3, 481, 164 },
17376 { 0xA59BC234DB398C25, 508, 172 },
17377 { 0xF6C69A72A3989F5C, 534, 180 },
17378 { 0xB7DCBF5354E9BECE, 561, 188 },
17379 { 0x88FCF317F22241E2, 588, 196 },
17380 { 0xCC20CE9BD35C78A5, 614, 204 },
17381 { 0x98165AF37B2153DF, 641, 212 },
17382 { 0xE2A0B5DC971F303A, 667, 220 },
17383 { 0xA8D9D1535CE3B396, 694, 228 },
17384 { 0xFB9B7CD9A4A7443C, 720, 236 },
17385 { 0xBB764C4CA7A44410, 747, 244 },
17386 { 0x8BAB8EEFB6409C1A, 774, 252 },
17387 { 0xD01FEF10A657842C, 800, 260 },
17388 { 0x9B10A4E5E9913129, 827, 268 },
17389 { 0xE7109BFBA19C0C9D, 853, 276 },
17390 { 0xAC2820D9623BF429, 880, 284 },
17391 { 0x80444B5E7AA7CF85, 907, 292 },
17392 { 0xBF21E44003ACDD2D, 933, 300 },
17393 { 0x8E679C2F5E44FF8F, 960, 308 },
17394 { 0xD433179D9C8CB841, 986, 316 },
17395 { 0x9E19DB92B4E31BA9, 1013, 324 },
17396 }
17397 };
17398
17399 // This computation gives exactly the same results for k as
17400 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17401 // for |e| <= 1500, but doesn't require floating-point operations.
17402 // NB: log_10(2) ~= 78913 / 2^18
17403 JSON_ASSERT(e >= -1500);
17404 JSON_ASSERT(e <= 1500);
17405 const int f = kAlpha - e - 1;
17406 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17407
17408 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17409 JSON_ASSERT(index >= 0);
17410 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17411
17412 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17413 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17414 JSON_ASSERT(kGamma >= cached.e + e + 64);
17415
17416 return cached;
17417}
17418
17423inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17424{
17425 // LCOV_EXCL_START
17426 if (n >= 1000000000)
17427 {
17428 pow10 = 1000000000;
17429 return 10;
17430 }
17431 // LCOV_EXCL_STOP
17432 if (n >= 100000000)
17433 {
17434 pow10 = 100000000;
17435 return 9;
17436 }
17437 if (n >= 10000000)
17438 {
17439 pow10 = 10000000;
17440 return 8;
17441 }
17442 if (n >= 1000000)
17443 {
17444 pow10 = 1000000;
17445 return 7;
17446 }
17447 if (n >= 100000)
17448 {
17449 pow10 = 100000;
17450 return 6;
17451 }
17452 if (n >= 10000)
17453 {
17454 pow10 = 10000;
17455 return 5;
17456 }
17457 if (n >= 1000)
17458 {
17459 pow10 = 1000;
17460 return 4;
17461 }
17462 if (n >= 100)
17463 {
17464 pow10 = 100;
17465 return 3;
17466 }
17467 if (n >= 10)
17468 {
17469 pow10 = 10;
17470 return 2;
17471 }
17472
17473 pow10 = 1;
17474 return 1;
17475}
17476
17477inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17478 std::uint64_t rest, std::uint64_t ten_k)
17479{
17480 JSON_ASSERT(len >= 1);
17481 JSON_ASSERT(dist <= delta);
17482 JSON_ASSERT(rest <= delta);
17483 JSON_ASSERT(ten_k > 0);
17484
17485 // <--------------------------- delta ---->
17486 // <---- dist --------->
17487 // --------------[------------------+-------------------]--------------
17488 // M- w M+
17489 //
17490 // ten_k
17491 // <------>
17492 // <---- rest ---->
17493 // --------------[------------------+----+--------------]--------------
17494 // w V
17495 // = buf * 10^k
17496 //
17497 // ten_k represents a unit-in-the-last-place in the decimal representation
17498 // stored in buf.
17499 // Decrement buf by ten_k while this takes buf closer to w.
17500
17501 // The tests are written in this order to avoid overflow in unsigned
17502 // integer arithmetic.
17503
17504 while (rest < dist
17505 && delta - rest >= ten_k
17506 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17507 {
17508 JSON_ASSERT(buf[len - 1] != '0');
17509 buf[len - 1]--;
17510 rest += ten_k;
17511 }
17512}
17513
17518inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17519 diyfp M_minus, diyfp w, diyfp M_plus)
17520{
17521 static_assert(kAlpha >= -60, "internal error");
17522 static_assert(kGamma <= -32, "internal error");
17523
17524 // Generates the digits (and the exponent) of a decimal floating-point
17525 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17526 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17527 //
17528 // <--------------------------- delta ---->
17529 // <---- dist --------->
17530 // --------------[------------------+-------------------]--------------
17531 // M- w M+
17532 //
17533 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17534 // V is in [M-,M+].
17535
17536 JSON_ASSERT(M_plus.e >= kAlpha);
17537 JSON_ASSERT(M_plus.e <= kGamma);
17538
17539 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17540 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17541
17542 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17543 //
17544 // M+ = f * 2^e
17545 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17546 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17547 // = p1 + p2 * 2^e
17548
17549 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17550
17551 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17552 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17553
17554 // 1)
17555 //
17556 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17557
17558 JSON_ASSERT(p1 > 0);
17559
17560 std::uint32_t pow10{};
17561 const int k = find_largest_pow10(p1, pow10);
17562
17563 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17564 //
17565 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17566 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17567 //
17568 // M+ = p1 + p2 * 2^e
17569 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17570 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17571 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17572 //
17573 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17574 //
17575 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17576 //
17577 // but stop as soon as
17578 //
17579 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17580
17581 int n = k;
17582 while (n > 0)
17583 {
17584 // Invariants:
17585 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17586 // pow10 = 10^(n-1) <= p1 < 10^n
17587 //
17588 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17589 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17590 //
17591 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17592 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17593 //
17594 JSON_ASSERT(d <= 9);
17595 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17596 //
17597 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17598 //
17599 p1 = r;
17600 n--;
17601 //
17602 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17603 // pow10 = 10^n
17604 //
17605
17606 // Now check if enough digits have been generated.
17607 // Compute
17608 //
17609 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17610 //
17611 // Note:
17612 // Since rest and delta share the same exponent e, it suffices to
17613 // compare the significands.
17614 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17615 if (rest <= delta)
17616 {
17617 // V = buffer * 10^n, with M- <= V <= M+.
17618
17619 decimal_exponent += n;
17620
17621 // We may now just stop. But instead look if the buffer could be
17622 // decremented to bring V closer to w.
17623 //
17624 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17625 // The rounding procedure works with diyfp's with an implicit
17626 // exponent of e.
17627 //
17628 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17629 //
17630 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17631 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17632
17633 return;
17634 }
17635
17636 pow10 /= 10;
17637 //
17638 // pow10 = 10^(n-1) <= p1 < 10^n
17639 // Invariants restored.
17640 }
17641
17642 // 2)
17643 //
17644 // The digits of the integral part have been generated:
17645 //
17646 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17647 // = buffer + p2 * 2^e
17648 //
17649 // Now generate the digits of the fractional part p2 * 2^e.
17650 //
17651 // Note:
17652 // No decimal point is generated: the exponent is adjusted instead.
17653 //
17654 // p2 actually represents the fraction
17655 //
17656 // p2 * 2^e
17657 // = p2 / 2^-e
17658 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17659 //
17660 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17661 //
17662 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17663 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17664 //
17665 // using
17666 //
17667 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17668 // = ( d) * 2^-e + ( r)
17669 //
17670 // or
17671 // 10^m * p2 * 2^e = d + r * 2^e
17672 //
17673 // i.e.
17674 //
17675 // M+ = buffer + p2 * 2^e
17676 // = buffer + 10^-m * (d + r * 2^e)
17677 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17678 //
17679 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17680
17681 JSON_ASSERT(p2 > delta);
17682
17683 int m = 0;
17684 for (;;)
17685 {
17686 // Invariant:
17687 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17688 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17689 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17690 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17691 //
17692 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17693 p2 *= 10;
17694 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17695 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17696 //
17697 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17698 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17699 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17700 //
17701 JSON_ASSERT(d <= 9);
17702 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17703 //
17704 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17705 //
17706 p2 = r;
17707 m++;
17708 //
17709 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17710 // Invariant restored.
17711
17712 // Check if enough digits have been generated.
17713 //
17714 // 10^-m * p2 * 2^e <= delta * 2^e
17715 // p2 * 2^e <= 10^m * delta * 2^e
17716 // p2 <= 10^m * delta
17717 delta *= 10;
17718 dist *= 10;
17719 if (p2 <= delta)
17720 {
17721 break;
17722 }
17723 }
17724
17725 // V = buffer * 10^-m, with M- <= V <= M+.
17726
17727 decimal_exponent -= m;
17728
17729 // 1 ulp in the decimal representation is now 10^-m.
17730 // Since delta and dist are now scaled by 10^m, we need to do the
17731 // same with ulp in order to keep the units in sync.
17732 //
17733 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17734 //
17735 const std::uint64_t ten_m = one.f;
17736 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17737
17738 // By construction this algorithm generates the shortest possible decimal
17739 // number (Loitsch, Theorem 6.2) which rounds back to w.
17740 // For an input number of precision p, at least
17741 //
17742 // N = 1 + ceil(p * log_10(2))
17743 //
17744 // decimal digits are sufficient to identify all binary floating-point
17745 // numbers (Matula, "In-and-Out conversions").
17746 // This implies that the algorithm does not produce more than N decimal
17747 // digits.
17748 //
17749 // N = 17 for p = 53 (IEEE double precision)
17750 // N = 9 for p = 24 (IEEE single precision)
17751}
17752
17759inline void grisu2(char* buf, int& len, int& decimal_exponent,
17760 diyfp m_minus, diyfp v, diyfp m_plus)
17761{
17762 JSON_ASSERT(m_plus.e == m_minus.e);
17763 JSON_ASSERT(m_plus.e == v.e);
17764
17765 // --------(-----------------------+-----------------------)-------- (A)
17766 // m- v m+
17767 //
17768 // --------------------(-----------+-----------------------)-------- (B)
17769 // m- v m+
17770 //
17771 // First scale v (and m- and m+) such that the exponent is in the range
17772 // [alpha, gamma].
17773
17774 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17775
17776 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17777
17778 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17779 const diyfp w = diyfp::mul(v, c_minus_k);
17780 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17781 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17782
17783 // ----(---+---)---------------(---+---)---------------(---+---)----
17784 // w- w w+
17785 // = c*m- = c*v = c*m+
17786 //
17787 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17788 // w+ are now off by a small amount.
17789 // In fact:
17790 //
17791 // w - v * 10^k < 1 ulp
17792 //
17793 // To account for this inaccuracy, add resp. subtract 1 ulp.
17794 //
17795 // --------+---[---------------(---+---)---------------]---+--------
17796 // w- M- w M+ w+
17797 //
17798 // Now any number in [M-, M+] (bounds included) will round to w when input,
17799 // regardless of how the input rounding algorithm breaks ties.
17800 //
17801 // And digit_gen generates the shortest possible such number in [M-, M+].
17802 // Note that this does not mean that Grisu2 always generates the shortest
17803 // possible number in the interval (m-, m+).
17804 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17805 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17806
17807 decimal_exponent = -cached.k; // = -(-k) = k
17808
17809 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17810}
17811
17817template<typename FloatType>
17819void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17820{
17821 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17822 "internal error: not enough precision");
17823
17824 JSON_ASSERT(std::isfinite(value));
17825 JSON_ASSERT(value > 0);
17826
17827 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17828 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17829 // decimal representations are not exactly "short".
17830 //
17831 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17832 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17833 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17834 // does.
17835 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17836 // representation using the corresponding std::from_chars function recovers value exactly". That
17837 // indicates that single precision floating-point numbers should be recovered using
17838 // 'std::strtof'.
17839 //
17840 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17841 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17842 // value is off by 1 ulp.
17843#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17844 const boundaries w = compute_boundaries(static_cast<double>(value));
17845#else
17847#endif
17848
17849 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17850}
17851
17859inline char* append_exponent(char* buf, int e)
17860{
17861 JSON_ASSERT(e > -1000);
17862 JSON_ASSERT(e < 1000);
17863
17864 if (e < 0)
17865 {
17866 e = -e;
17867 *buf++ = '-';
17868 }
17869 else
17870 {
17871 *buf++ = '+';
17872 }
17873
17874 auto k = static_cast<std::uint32_t>(e);
17875 if (k < 10)
17876 {
17877 // Always print at least two digits in the exponent.
17878 // This is for compatibility with printf("%g").
17879 *buf++ = '0';
17880 *buf++ = static_cast<char>('0' + k);
17881 }
17882 else if (k < 100)
17883 {
17884 *buf++ = static_cast<char>('0' + k / 10);
17885 k %= 10;
17886 *buf++ = static_cast<char>('0' + k);
17887 }
17888 else
17889 {
17890 *buf++ = static_cast<char>('0' + k / 100);
17891 k %= 100;
17892 *buf++ = static_cast<char>('0' + k / 10);
17893 k %= 10;
17894 *buf++ = static_cast<char>('0' + k);
17895 }
17896
17897 return buf;
17898}
17899
17911inline char* format_buffer(char* buf, int len, int decimal_exponent,
17912 int min_exp, int max_exp)
17913{
17914 JSON_ASSERT(min_exp < 0);
17915 JSON_ASSERT(max_exp > 0);
17916
17917 const int k = len;
17918 const int n = len + decimal_exponent;
17919
17920 // v = buf * 10^(n-k)
17921 // k is the length of the buffer (number of decimal digits)
17922 // n is the position of the decimal point relative to the start of the buffer.
17923
17924 if (k <= n && n <= max_exp)
17925 {
17926 // digits[000]
17927 // len <= max_exp + 2
17928
17929 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17930 // Make it look like a floating-point number (#362, #378)
17931 buf[n + 0] = '.';
17932 buf[n + 1] = '0';
17933 return buf + (static_cast<size_t>(n) + 2);
17934 }
17935
17936 if (0 < n && n <= max_exp)
17937 {
17938 // dig.its
17939 // len <= max_digits10 + 1
17940
17941 JSON_ASSERT(k > n);
17942
17943 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17944 buf[n] = '.';
17945 return buf + (static_cast<size_t>(k) + 1U);
17946 }
17947
17948 if (min_exp < n && n <= 0)
17949 {
17950 // 0.[000]digits
17951 // len <= 2 + (-min_exp - 1) + max_digits10
17952
17953 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17954 buf[0] = '0';
17955 buf[1] = '.';
17956 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17957 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17958 }
17959
17960 if (k == 1)
17961 {
17962 // dE+123
17963 // len <= 1 + 5
17964
17965 buf += 1;
17966 }
17967 else
17968 {
17969 // d.igitsE+123
17970 // len <= max_digits10 + 1 + 5
17971
17972 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17973 buf[1] = '.';
17974 buf += 1 + static_cast<size_t>(k);
17975 }
17976
17977 *buf++ = 'e';
17978 return append_exponent(buf, n - 1);
17979}
17980
17981} // namespace dtoa_impl
17982
17993template<typename FloatType>
17996char* to_chars(char* first, const char* last, FloatType value)
17997{
17998 static_cast<void>(last); // maybe unused - fix warning
17999 JSON_ASSERT(std::isfinite(value));
18000
18001 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18002 if (std::signbit(value))
18003 {
18004 value = -value;
18005 *first++ = '-';
18006 }
18007
18008#ifdef __GNUC__
18009#pragma GCC diagnostic push
18010#pragma GCC diagnostic ignored "-Wfloat-equal"
18011#endif
18012 if (value == 0) // +-0
18013 {
18014 *first++ = '0';
18015 // Make it look like a floating-point number (#362, #378)
18016 *first++ = '.';
18017 *first++ = '0';
18018 return first;
18019 }
18020#ifdef __GNUC__
18021#pragma GCC diagnostic pop
18022#endif
18023
18024 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18025
18026 // Compute v = buffer * 10^decimal_exponent.
18027 // The decimal digits are stored in the buffer, which needs to be interpreted
18028 // as an unsigned decimal integer.
18029 // len is the length of the buffer, i.e. the number of decimal digits.
18030 int len = 0;
18031 int decimal_exponent = 0;
18032 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18033
18034 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18035
18036 // Format the buffer like printf("%.*g", prec, value)
18037 constexpr int kMinExp = -4;
18038 // Use digits10 here to increase compatibility with version 2.
18039 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18040
18041 JSON_ASSERT(last - first >= kMaxExp + 2);
18042 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18043 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18044
18045 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18046}
18047
18048} // namespace detail
18050
18051// #include <nlohmann/detail/exceptions.hpp>
18052
18053// #include <nlohmann/detail/macro_scope.hpp>
18054
18055// #include <nlohmann/detail/meta/cpp_future.hpp>
18056
18057// #include <nlohmann/detail/output/binary_writer.hpp>
18058
18059// #include <nlohmann/detail/output/output_adapters.hpp>
18060
18061// #include <nlohmann/detail/string_concat.hpp>
18062
18063// #include <nlohmann/detail/value_t.hpp>
18064
18065
18067namespace detail
18068{
18069
18071// serialization //
18073
18076{
18077 strict,
18078 replace,
18079 ignore
18080};
18081
18082template<typename BasicJsonType>
18084{
18085 using string_t = typename BasicJsonType::string_t;
18086 using number_float_t = typename BasicJsonType::number_float_t;
18087 using number_integer_t = typename BasicJsonType::number_integer_t;
18088 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18089 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18090 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18091 static constexpr std::uint8_t UTF8_REJECT = 1;
18092
18093 public:
18101 : o(std::move(s))
18102 , loc(std::localeconv())
18103 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18104 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18105 , indent_char(ichar)
18107 , error_handler(error_handler_)
18108 {}
18109
18110 // delete because of pointer members
18111 serializer(const serializer&) = delete;
18115 ~serializer() = default;
18116
18139 void dump(const BasicJsonType& val,
18140 const bool pretty_print,
18141 const bool ensure_ascii,
18142 const unsigned int indent_step,
18143 const unsigned int current_indent = 0)
18144 {
18145 switch (val.m_data.m_type)
18146 {
18147 case value_t::object:
18148 {
18149 if (val.m_data.m_value.object->empty())
18150 {
18151 o->write_characters("{}", 2);
18152 return;
18153 }
18154
18155 if (pretty_print)
18156 {
18157 o->write_characters("{\n", 2);
18158
18159 // variable to hold indentation for recursive calls
18160 const auto new_indent = current_indent + indent_step;
18161 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18162 {
18163 indent_string.resize(indent_string.size() * 2, ' ');
18164 }
18165
18166 // first n-1 elements
18167 auto i = val.m_data.m_value.object->cbegin();
18168 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18169 {
18170 o->write_characters(indent_string.c_str(), new_indent);
18171 o->write_character('\"');
18172 dump_escaped(i->first, ensure_ascii);
18173 o->write_characters("\": ", 3);
18174 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18175 o->write_characters(",\n", 2);
18176 }
18177
18178 // last element
18179 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18180 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18181 o->write_characters(indent_string.c_str(), new_indent);
18182 o->write_character('\"');
18183 dump_escaped(i->first, ensure_ascii);
18184 o->write_characters("\": ", 3);
18185 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18186
18187 o->write_character('\n');
18188 o->write_characters(indent_string.c_str(), current_indent);
18189 o->write_character('}');
18190 }
18191 else
18192 {
18193 o->write_character('{');
18194
18195 // first n-1 elements
18196 auto i = val.m_data.m_value.object->cbegin();
18197 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18198 {
18199 o->write_character('\"');
18200 dump_escaped(i->first, ensure_ascii);
18201 o->write_characters("\":", 2);
18202 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18203 o->write_character(',');
18204 }
18205
18206 // last element
18207 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18208 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18209 o->write_character('\"');
18210 dump_escaped(i->first, ensure_ascii);
18211 o->write_characters("\":", 2);
18212 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18213
18214 o->write_character('}');
18215 }
18216
18217 return;
18218 }
18219
18220 case value_t::array:
18221 {
18222 if (val.m_data.m_value.array->empty())
18223 {
18224 o->write_characters("[]", 2);
18225 return;
18226 }
18227
18228 if (pretty_print)
18229 {
18230 o->write_characters("[\n", 2);
18231
18232 // variable to hold indentation for recursive calls
18233 const auto new_indent = current_indent + indent_step;
18234 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18235 {
18236 indent_string.resize(indent_string.size() * 2, ' ');
18237 }
18238
18239 // first n-1 elements
18240 for (auto i = val.m_data.m_value.array->cbegin();
18241 i != val.m_data.m_value.array->cend() - 1; ++i)
18242 {
18243 o->write_characters(indent_string.c_str(), new_indent);
18244 dump(*i, true, ensure_ascii, indent_step, new_indent);
18245 o->write_characters(",\n", 2);
18246 }
18247
18248 // last element
18249 JSON_ASSERT(!val.m_data.m_value.array->empty());
18250 o->write_characters(indent_string.c_str(), new_indent);
18251 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18252
18253 o->write_character('\n');
18254 o->write_characters(indent_string.c_str(), current_indent);
18255 o->write_character(']');
18256 }
18257 else
18258 {
18259 o->write_character('[');
18260
18261 // first n-1 elements
18262 for (auto i = val.m_data.m_value.array->cbegin();
18263 i != val.m_data.m_value.array->cend() - 1; ++i)
18264 {
18265 dump(*i, false, ensure_ascii, indent_step, current_indent);
18266 o->write_character(',');
18267 }
18268
18269 // last element
18270 JSON_ASSERT(!val.m_data.m_value.array->empty());
18271 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18272
18273 o->write_character(']');
18274 }
18275
18276 return;
18277 }
18278
18279 case value_t::string:
18280 {
18281 o->write_character('\"');
18282 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18283 o->write_character('\"');
18284 return;
18285 }
18286
18287 case value_t::binary:
18288 {
18289 if (pretty_print)
18290 {
18291 o->write_characters("{\n", 2);
18292
18293 // variable to hold indentation for recursive calls
18294 const auto new_indent = current_indent + indent_step;
18295 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18296 {
18297 indent_string.resize(indent_string.size() * 2, ' ');
18298 }
18299
18300 o->write_characters(indent_string.c_str(), new_indent);
18301
18302 o->write_characters("\"bytes\": [", 10);
18303
18304 if (!val.m_data.m_value.binary->empty())
18305 {
18306 for (auto i = val.m_data.m_value.binary->cbegin();
18307 i != val.m_data.m_value.binary->cend() - 1; ++i)
18308 {
18309 dump_integer(*i);
18310 o->write_characters(", ", 2);
18311 }
18312 dump_integer(val.m_data.m_value.binary->back());
18313 }
18314
18315 o->write_characters("],\n", 3);
18316 o->write_characters(indent_string.c_str(), new_indent);
18317
18318 o->write_characters("\"subtype\": ", 11);
18319 if (val.m_data.m_value.binary->has_subtype())
18320 {
18321 dump_integer(val.m_data.m_value.binary->subtype());
18322 }
18323 else
18324 {
18325 o->write_characters("null", 4);
18326 }
18327 o->write_character('\n');
18328 o->write_characters(indent_string.c_str(), current_indent);
18329 o->write_character('}');
18330 }
18331 else
18332 {
18333 o->write_characters("{\"bytes\":[", 10);
18334
18335 if (!val.m_data.m_value.binary->empty())
18336 {
18337 for (auto i = val.m_data.m_value.binary->cbegin();
18338 i != val.m_data.m_value.binary->cend() - 1; ++i)
18339 {
18340 dump_integer(*i);
18341 o->write_character(',');
18342 }
18343 dump_integer(val.m_data.m_value.binary->back());
18344 }
18345
18346 o->write_characters("],\"subtype\":", 12);
18347 if (val.m_data.m_value.binary->has_subtype())
18348 {
18349 dump_integer(val.m_data.m_value.binary->subtype());
18350 o->write_character('}');
18351 }
18352 else
18353 {
18354 o->write_characters("null}", 5);
18355 }
18356 }
18357 return;
18358 }
18359
18360 case value_t::boolean:
18361 {
18362 if (val.m_data.m_value.boolean)
18363 {
18364 o->write_characters("true", 4);
18365 }
18366 else
18367 {
18368 o->write_characters("false", 5);
18369 }
18370 return;
18371 }
18372
18374 {
18375 dump_integer(val.m_data.m_value.number_integer);
18376 return;
18377 }
18378
18380 {
18381 dump_integer(val.m_data.m_value.number_unsigned);
18382 return;
18383 }
18384
18386 {
18387 dump_float(val.m_data.m_value.number_float);
18388 return;
18389 }
18390
18391 case value_t::discarded:
18392 {
18393 o->write_characters("<discarded>", 11);
18394 return;
18395 }
18396
18397 case value_t::null:
18398 {
18399 o->write_characters("null", 4);
18400 return;
18401 }
18402
18403 default: // LCOV_EXCL_LINE
18404 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18405 }
18406 }
18407
18423 void dump_escaped(const string_t& s, const bool ensure_ascii)
18424 {
18425 std::uint32_t codepoint{};
18426 std::uint8_t state = UTF8_ACCEPT;
18427 std::size_t bytes = 0; // number of bytes written to string_buffer
18428
18429 // number of bytes written at the point of the last valid byte
18431 std::size_t undumped_chars = 0;
18432
18433 for (std::size_t i = 0; i < s.size(); ++i)
18434 {
18435 const auto byte = static_cast<std::uint8_t>(s[i]);
18436
18437 switch (decode(state, codepoint, byte))
18438 {
18439 case UTF8_ACCEPT: // decode found a new code point
18440 {
18441 switch (codepoint)
18442 {
18443 case 0x08: // backspace
18444 {
18445 string_buffer[bytes++] = '\\';
18446 string_buffer[bytes++] = 'b';
18447 break;
18448 }
18449
18450 case 0x09: // horizontal tab
18451 {
18452 string_buffer[bytes++] = '\\';
18453 string_buffer[bytes++] = 't';
18454 break;
18455 }
18456
18457 case 0x0A: // newline
18458 {
18459 string_buffer[bytes++] = '\\';
18460 string_buffer[bytes++] = 'n';
18461 break;
18462 }
18463
18464 case 0x0C: // formfeed
18465 {
18466 string_buffer[bytes++] = '\\';
18467 string_buffer[bytes++] = 'f';
18468 break;
18469 }
18470
18471 case 0x0D: // carriage return
18472 {
18473 string_buffer[bytes++] = '\\';
18474 string_buffer[bytes++] = 'r';
18475 break;
18476 }
18477
18478 case 0x22: // quotation mark
18479 {
18480 string_buffer[bytes++] = '\\';
18481 string_buffer[bytes++] = '\"';
18482 break;
18483 }
18484
18485 case 0x5C: // reverse solidus
18486 {
18487 string_buffer[bytes++] = '\\';
18488 string_buffer[bytes++] = '\\';
18489 break;
18490 }
18491
18492 default:
18493 {
18494 // escape control characters (0x00..0x1F) or, if
18495 // ensure_ascii parameter is used, non-ASCII characters
18496 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18497 {
18498 if (codepoint <= 0xFFFF)
18499 {
18500 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18501 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18502 static_cast<std::uint16_t>(codepoint)));
18503 bytes += 6;
18504 }
18505 else
18506 {
18507 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18508 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18509 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18510 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18511 bytes += 12;
18512 }
18513 }
18514 else
18515 {
18516 // copy byte to buffer (all previous bytes
18517 // been copied have in default case above)
18518 string_buffer[bytes++] = s[i];
18519 }
18520 break;
18521 }
18522 }
18523
18524 // write buffer and reset index; there must be 13 bytes
18525 // left, as this is the maximal number of bytes to be
18526 // written ("\uxxxx\uxxxx\0") for one code point
18527 if (string_buffer.size() - bytes < 13)
18528 {
18529 o->write_characters(string_buffer.data(), bytes);
18530 bytes = 0;
18531 }
18532
18533 // remember the byte position of this accept
18535 undumped_chars = 0;
18536 break;
18537 }
18538
18539 case UTF8_REJECT: // decode found invalid UTF-8 byte
18540 {
18541 switch (error_handler)
18542 {
18544 {
18545 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18546 }
18547
18550 {
18551 // in case we saw this character the first time, we
18552 // would like to read it again, because the byte
18553 // may be OK for itself, but just not OK for the
18554 // previous sequence
18555 if (undumped_chars > 0)
18556 {
18557 --i;
18558 }
18559
18560 // reset length buffer to the last accepted index;
18561 // thus removing/ignoring the invalid characters
18563
18565 {
18566 // add a replacement character
18567 if (ensure_ascii)
18568 {
18569 string_buffer[bytes++] = '\\';
18570 string_buffer[bytes++] = 'u';
18571 string_buffer[bytes++] = 'f';
18572 string_buffer[bytes++] = 'f';
18573 string_buffer[bytes++] = 'f';
18574 string_buffer[bytes++] = 'd';
18575 }
18576 else
18577 {
18581 }
18582
18583 // write buffer and reset index; there must be 13 bytes
18584 // left, as this is the maximal number of bytes to be
18585 // written ("\uxxxx\uxxxx\0") for one code point
18586 if (string_buffer.size() - bytes < 13)
18587 {
18588 o->write_characters(string_buffer.data(), bytes);
18589 bytes = 0;
18590 }
18591
18593 }
18594
18595 undumped_chars = 0;
18596
18597 // continue processing the string
18598 state = UTF8_ACCEPT;
18599 break;
18600 }
18601
18602 default: // LCOV_EXCL_LINE
18603 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18604 }
18605 break;
18606 }
18607
18608 default: // decode found yet incomplete multi-byte code point
18609 {
18610 if (!ensure_ascii)
18611 {
18612 // code point will not be escaped - copy byte to buffer
18613 string_buffer[bytes++] = s[i];
18614 }
18616 break;
18617 }
18618 }
18619 }
18620
18621 // we finished processing the string
18622 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18623 {
18624 // write buffer
18625 if (bytes > 0)
18626 {
18627 o->write_characters(string_buffer.data(), bytes);
18628 }
18629 }
18630 else
18631 {
18632 // we finish reading, but do not accept: string was incomplete
18633 switch (error_handler)
18634 {
18636 {
18637 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18638 }
18639
18641 {
18642 // write all accepted bytes
18643 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18644 break;
18645 }
18646
18648 {
18649 // write all accepted bytes
18650 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18651 // add a replacement character
18652 if (ensure_ascii)
18653 {
18654 o->write_characters("\\ufffd", 6);
18655 }
18656 else
18657 {
18658 o->write_characters("\xEF\xBF\xBD", 3);
18659 }
18660 break;
18661 }
18662
18663 default: // LCOV_EXCL_LINE
18664 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18665 }
18666 }
18667 }
18668
18669 private:
18678 inline unsigned int count_digits(number_unsigned_t x) noexcept
18679 {
18680 unsigned int n_digits = 1;
18681 for (;;)
18682 {
18683 if (x < 10)
18684 {
18685 return n_digits;
18686 }
18687 if (x < 100)
18688 {
18689 return n_digits + 1;
18690 }
18691 if (x < 1000)
18692 {
18693 return n_digits + 2;
18694 }
18695 if (x < 10000)
18696 {
18697 return n_digits + 3;
18698 }
18699 x = x / 10000u;
18700 n_digits += 4;
18701 }
18702 }
18703
18709 static std::string hex_bytes(std::uint8_t byte)
18710 {
18711 std::string result = "FF";
18712 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18713 result[0] = nibble_to_hex[byte / 16];
18714 result[1] = nibble_to_hex[byte % 16];
18715 return result;
18716 }
18717
18718 // templates to avoid warnings about useless casts
18719 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18720 bool is_negative_number(NumberType x)
18721 {
18722 return x < 0;
18723 }
18724
18725 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18726 bool is_negative_number(NumberType /*unused*/)
18727 {
18728 return false;
18729 }
18730
18740 template < typename NumberType, detail::enable_if_t <
18741 std::is_integral<NumberType>::value ||
18742 std::is_same<NumberType, number_unsigned_t>::value ||
18743 std::is_same<NumberType, number_integer_t>::value ||
18744 std::is_same<NumberType, binary_char_t>::value,
18745 int > = 0 >
18746 void dump_integer(NumberType x)
18747 {
18748 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18749 {
18750 {
18751 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18752 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18753 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18754 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18755 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18756 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18757 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18758 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18759 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18760 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18761 }
18762 };
18763
18764 // special case for "0"
18765 if (x == 0)
18766 {
18767 o->write_character('0');
18768 return;
18769 }
18770
18771 // use a pointer to fill the buffer
18772 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18773
18774 number_unsigned_t abs_value;
18775
18776 unsigned int n_chars{};
18777
18778 if (is_negative_number(x))
18779 {
18780 *buffer_ptr = '-';
18781 abs_value = remove_sign(static_cast<number_integer_t>(x));
18782
18783 // account one more byte for the minus sign
18784 n_chars = 1 + count_digits(abs_value);
18785 }
18786 else
18787 {
18788 abs_value = static_cast<number_unsigned_t>(x);
18789 n_chars = count_digits(abs_value);
18790 }
18791
18792 // spare 1 byte for '\0'
18793 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18794
18795 // jump to the end to generate the string from backward,
18796 // so we later avoid reversing the result
18797 buffer_ptr += n_chars;
18798
18799 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18800 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18801 while (abs_value >= 100)
18802 {
18803 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18804 abs_value /= 100;
18805 *(--buffer_ptr) = digits_to_99[digits_index][1];
18806 *(--buffer_ptr) = digits_to_99[digits_index][0];
18807 }
18808
18809 if (abs_value >= 10)
18810 {
18811 const auto digits_index = static_cast<unsigned>(abs_value);
18812 *(--buffer_ptr) = digits_to_99[digits_index][1];
18813 *(--buffer_ptr) = digits_to_99[digits_index][0];
18814 }
18815 else
18816 {
18817 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18818 }
18819
18820 o->write_characters(number_buffer.data(), n_chars);
18821 }
18822
18831 void dump_float(number_float_t x)
18832 {
18833 // NaN / inf
18834 if (!std::isfinite(x))
18835 {
18836 o->write_characters("null", 4);
18837 return;
18838 }
18839
18840 // If number_float_t is an IEEE-754 single or double precision number,
18841 // use the Grisu2 algorithm to produce short numbers which are
18842 // guaranteed to round-trip, using strtof and strtod, resp.
18843 //
18844 // NB: The test below works if <long double> == <double>.
18845 static constexpr bool is_ieee_single_or_double
18846 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18847 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18848
18849 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18850 }
18851
18852 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18853 {
18854 auto* begin = number_buffer.data();
18855 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18856
18857 o->write_characters(begin, static_cast<size_t>(end - begin));
18858 }
18859
18860 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18861 {
18862 // get number of digits for a float -> text -> float round-trip
18863 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18864
18865 // the actual conversion
18866 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18867 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18868
18869 // negative value indicates an error
18870 JSON_ASSERT(len > 0);
18871 // check if buffer was large enough
18872 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18873
18874 // erase thousands separator
18875 if (thousands_sep != '\0')
18876 {
18877 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18878 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18879 std::fill(end, number_buffer.end(), '\0');
18880 JSON_ASSERT((end - number_buffer.begin()) <= len);
18881 len = (end - number_buffer.begin());
18882 }
18883
18884 // convert decimal point to '.'
18885 if (decimal_point != '\0' && decimal_point != '.')
18886 {
18887 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18888 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18889 if (dec_pos != number_buffer.end())
18890 {
18891 *dec_pos = '.';
18892 }
18893 }
18894
18895 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18896
18897 // determine if we need to append ".0"
18898 const bool value_is_int_like =
18899 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18900 [](char c)
18901 {
18902 return c == '.' || c == 'e';
18903 });
18904
18905 if (value_is_int_like)
18906 {
18907 o->write_characters(".0", 2);
18908 }
18909 }
18910
18932 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18933 {
18934 static const std::array<std::uint8_t, 400> utf8d =
18935 {
18936 {
18937 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
18938 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
18939 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
18940 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
18941 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
18942 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
18943 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
18944 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18945 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18946 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18947 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
18948 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
18949 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
18950 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
18951 }
18952 };
18953
18954 JSON_ASSERT(byte < utf8d.size());
18955 const std::uint8_t type = utf8d[byte];
18956
18957 codep = (state != UTF8_ACCEPT)
18958 ? (byte & 0x3fu) | (codep << 6u)
18959 : (0xFFu >> type) & (byte);
18960
18961 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18962 JSON_ASSERT(index < utf8d.size());
18963 state = utf8d[index];
18964 return state;
18965 }
18966
18967 /*
18968 * Overload to make the compiler happy while it is instantiating
18969 * dump_integer for number_unsigned_t.
18970 * Must never be called.
18971 */
18972 number_unsigned_t remove_sign(number_unsigned_t x)
18973 {
18974 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18975 return x; // LCOV_EXCL_LINE
18976 }
18977
18978 /*
18979 * Helper function for dump_integer
18980 *
18981 * This function takes a negative signed integer and returns its absolute
18982 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18983 * not directly remove the sign of an arbitrary signed integer as the
18984 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18985 * #1708 for details.
18986 */
18987 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18988 {
18989 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18990 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18991 }
18992
18993 private:
18995 output_adapter_t<char> o = nullptr;
18996
18998 std::array<char, 64> number_buffer{{}};
18999
19001 const std::lconv* loc = nullptr;
19003 const char thousands_sep = '\0';
19005 const char decimal_point = '\0';
19006
19008 std::array<char, 512> string_buffer{{}};
19009
19011 const char indent_char;
19014
19017};
19018
19019} // namespace detail
19021
19022// #include <nlohmann/detail/value_t.hpp>
19023
19024// #include <nlohmann/json_fwd.hpp>
19025
19026// #include <nlohmann/ordered_map.hpp>
19027// __ _____ _____ _____
19028// __| | __| | | | JSON for Modern C++
19029// | | |__ | | | | | | version 3.11.3
19030// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19031//
19032// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19033// SPDX-License-Identifier: MIT
19034
19035
19036
19037#include <functional> // equal_to, less
19038#include <initializer_list> // initializer_list
19039#include <iterator> // input_iterator_tag, iterator_traits
19040#include <memory> // allocator
19041#include <stdexcept> // for out_of_range
19042#include <type_traits> // enable_if, is_convertible
19043#include <utility> // pair
19044#include <vector> // vector
19045
19046// #include <nlohmann/detail/macro_scope.hpp>
19047
19048// #include <nlohmann/detail/meta/type_traits.hpp>
19049
19050
19052
19055template <class Key, class T, class IgnoredLess = std::less<Key>,
19056 class Allocator = std::allocator<std::pair<const Key, T>>>
19057 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19058{
19059 using key_type = Key;
19060 using mapped_type = T;
19061 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19062 using iterator = typename Container::iterator;
19063 using const_iterator = typename Container::const_iterator;
19064 using size_type = typename Container::size_type;
19065 using value_type = typename Container::value_type;
19066#ifdef JSON_HAS_CPP_14
19067 using key_compare = std::equal_to<>;
19068#else
19069 using key_compare = std::equal_to<Key>;
19070#endif
19071
19072 // Explicit constructors instead of `using Container::Container`
19073 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19074 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19075 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19076 template <class It>
19077 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19078 : Container{first, last, alloc} {}
19079 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19080 : Container{init, alloc} {}
19081
19082 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19083 {
19084 for (auto it = this->begin(); it != this->end(); ++it)
19085 {
19086 if (m_compare(it->first, key))
19087 {
19088 return {it, false};
19089 }
19090 }
19091 Container::emplace_back(key, std::forward<T>(t));
19092 return {std::prev(this->end()), true};
19093 }
19094
19095 template<class KeyType, detail::enable_if_t<
19097 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19098 {
19099 for (auto it = this->begin(); it != this->end(); ++it)
19100 {
19101 if (m_compare(it->first, key))
19102 {
19103 return {it, false};
19104 }
19105 }
19106 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19107 return {std::prev(this->end()), true};
19108 }
19109
19110 T& operator[](const key_type& key)
19111 {
19112 return emplace(key, T{}).first->second;
19113 }
19114
19115 template<class KeyType, detail::enable_if_t<
19117 T & operator[](KeyType && key)
19118 {
19119 return emplace(std::forward<KeyType>(key), T{}).first->second;
19120 }
19121
19122 const T& operator[](const key_type& key) const
19123 {
19124 return at(key);
19125 }
19126
19127 template<class KeyType, detail::enable_if_t<
19129 const T & operator[](KeyType && key) const
19130 {
19131 return at(std::forward<KeyType>(key));
19132 }
19133
19134 T& at(const key_type& key)
19135 {
19136 for (auto it = this->begin(); it != this->end(); ++it)
19137 {
19138 if (m_compare(it->first, key))
19139 {
19140 return it->second;
19141 }
19142 }
19143
19144 JSON_THROW(std::out_of_range("key not found"));
19145 }
19146
19147 template<class KeyType, detail::enable_if_t<
19149 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19150 {
19151 for (auto it = this->begin(); it != this->end(); ++it)
19152 {
19153 if (m_compare(it->first, key))
19154 {
19155 return it->second;
19156 }
19157 }
19158
19159 JSON_THROW(std::out_of_range("key not found"));
19160 }
19161
19162 const T& at(const key_type& key) const
19163 {
19164 for (auto it = this->begin(); it != this->end(); ++it)
19165 {
19166 if (m_compare(it->first, key))
19167 {
19168 return it->second;
19169 }
19170 }
19171
19172 JSON_THROW(std::out_of_range("key not found"));
19173 }
19174
19175 template<class KeyType, detail::enable_if_t<
19177 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19178 {
19179 for (auto it = this->begin(); it != this->end(); ++it)
19180 {
19181 if (m_compare(it->first, key))
19182 {
19183 return it->second;
19184 }
19185 }
19186
19187 JSON_THROW(std::out_of_range("key not found"));
19188 }
19189
19191 {
19192 for (auto it = this->begin(); it != this->end(); ++it)
19193 {
19194 if (m_compare(it->first, key))
19195 {
19196 // Since we cannot move const Keys, re-construct them in place
19197 for (auto next = it; ++next != this->end(); ++it)
19198 {
19199 it->~value_type(); // Destroy but keep allocation
19200 new (&*it) value_type{std::move(*next)};
19201 }
19202 Container::pop_back();
19203 return 1;
19204 }
19205 }
19206 return 0;
19207 }
19208
19209 template<class KeyType, detail::enable_if_t<
19211 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19212 {
19213 for (auto it = this->begin(); it != this->end(); ++it)
19214 {
19215 if (m_compare(it->first, key))
19216 {
19217 // Since we cannot move const Keys, re-construct them in place
19218 for (auto next = it; ++next != this->end(); ++it)
19219 {
19220 it->~value_type(); // Destroy but keep allocation
19221 new (&*it) value_type{std::move(*next)};
19222 }
19223 Container::pop_back();
19224 return 1;
19225 }
19226 }
19227 return 0;
19228 }
19229
19231 {
19232 return erase(pos, std::next(pos));
19233 }
19234
19236 {
19237 if (first == last)
19238 {
19239 return first;
19240 }
19241
19242 const auto elements_affected = std::distance(first, last);
19243 const auto offset = std::distance(Container::begin(), first);
19244
19245 // This is the start situation. We need to delete elements_affected
19246 // elements (3 in this example: e, f, g), and need to return an
19247 // iterator past the last deleted element (h in this example).
19248 // Note that offset is the distance from the start of the vector
19249 // to first. We will need this later.
19250
19251 // [ a, b, c, d, e, f, g, h, i, j ]
19252 // ^ ^
19253 // first last
19254
19255 // Since we cannot move const Keys, we re-construct them in place.
19256 // We start at first and re-construct (viz. copy) the elements from
19257 // the back of the vector. Example for first iteration:
19258
19259 // ,--------.
19260 // v | destroy e and re-construct with h
19261 // [ a, b, c, d, e, f, g, h, i, j ]
19262 // ^ ^
19263 // it it + elements_affected
19264
19265 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19266 {
19267 it->~value_type(); // destroy but keep allocation
19268 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19269 }
19270
19271 // [ a, b, c, d, h, i, j, h, i, j ]
19272 // ^ ^
19273 // first last
19274
19275 // remove the unneeded elements at the end of the vector
19276 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19277
19278 // [ a, b, c, d, h, i, j ]
19279 // ^ ^
19280 // first last
19281
19282 // first is now pointing past the last deleted element, but we cannot
19283 // use this iterator, because it may have been invalidated by the
19284 // resize call. Instead, we can return begin() + offset.
19285 return Container::begin() + offset;
19286 }
19287
19288 size_type count(const key_type& key) const
19289 {
19290 for (auto it = this->begin(); it != this->end(); ++it)
19291 {
19292 if (m_compare(it->first, key))
19293 {
19294 return 1;
19295 }
19296 }
19297 return 0;
19298 }
19299
19300 template<class KeyType, detail::enable_if_t<
19302 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19303 {
19304 for (auto it = this->begin(); it != this->end(); ++it)
19305 {
19306 if (m_compare(it->first, key))
19307 {
19308 return 1;
19309 }
19310 }
19311 return 0;
19312 }
19313
19315 {
19316 for (auto it = this->begin(); it != this->end(); ++it)
19317 {
19318 if (m_compare(it->first, key))
19319 {
19320 return it;
19321 }
19322 }
19323 return Container::end();
19324 }
19325
19326 template<class KeyType, detail::enable_if_t<
19328 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19329 {
19330 for (auto it = this->begin(); it != this->end(); ++it)
19331 {
19332 if (m_compare(it->first, key))
19333 {
19334 return it;
19335 }
19336 }
19337 return Container::end();
19338 }
19339
19340 const_iterator find(const key_type& key) const
19341 {
19342 for (auto it = this->begin(); it != this->end(); ++it)
19343 {
19344 if (m_compare(it->first, key))
19345 {
19346 return it;
19347 }
19348 }
19349 return Container::end();
19350 }
19351
19352 std::pair<iterator, bool> insert( value_type&& value )
19353 {
19354 return emplace(value.first, std::move(value.second));
19355 }
19356
19357 std::pair<iterator, bool> insert( const value_type& value )
19358 {
19359 for (auto it = this->begin(); it != this->end(); ++it)
19360 {
19361 if (m_compare(it->first, value.first))
19362 {
19363 return {it, false};
19364 }
19365 }
19366 Container::push_back(value);
19367 return {--this->end(), true};
19368 }
19369
19370 template<typename InputIt>
19371 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19372 std::input_iterator_tag>::value>::type;
19373
19374 template<typename InputIt, typename = require_input_iter<InputIt>>
19375 void insert(InputIt first, InputIt last)
19376 {
19377 for (auto it = first; it != last; ++it)
19378 {
19379 insert(*it);
19380 }
19381 }
19382
19383private:
19385};
19386
19388
19389
19390#if defined(JSON_HAS_CPP_17)
19391 #if JSON_HAS_STATIC_RTTI
19392 #include <any>
19393 #endif
19394 #include <string_view>
19395#endif
19396
19403
19423class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19424 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19425{
19426 private:
19427 template<detail::value_t> friend struct detail::external_constructor;
19428
19429 template<typename>
19430 friend class ::nlohmann::json_pointer;
19431 // can be restored when json_pointer backwards compatibility is removed
19432 // friend ::nlohmann::json_pointer<StringType>;
19433
19434 template<typename BasicJsonType, typename InputType>
19435 friend class ::nlohmann::detail::parser;
19436 friend ::nlohmann::detail::serializer<basic_json>;
19437 template<typename BasicJsonType>
19438 friend class ::nlohmann::detail::iter_impl;
19439 template<typename BasicJsonType, typename CharType>
19440 friend class ::nlohmann::detail::binary_writer;
19441 template<typename BasicJsonType, typename InputType, typename SAX>
19442 friend class ::nlohmann::detail::binary_reader;
19443 template<typename BasicJsonType>
19444 friend class ::nlohmann::detail::json_sax_dom_parser;
19445 template<typename BasicJsonType>
19446 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19447 friend class ::nlohmann::detail::exception;
19448
19450 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19451 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19452
19454 // convenience aliases for types residing in namespace detail;
19455 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19456
19457 template<typename InputAdapterType>
19458 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19459 InputAdapterType adapter,
19461 const bool allow_exceptions = true,
19462 const bool ignore_comments = false
19463 )
19464 {
19465 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19466 std::move(cb), allow_exceptions, ignore_comments);
19467 }
19468
19469 private:
19470 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19471 template<typename BasicJsonType>
19472 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19473 template<typename BasicJsonType>
19474 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19475 template<typename Iterator>
19476 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19477 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19478
19479 template<typename CharType>
19480 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19481
19482 template<typename InputType>
19483 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19484 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19485
19487 using serializer = ::nlohmann::detail::serializer<basic_json>;
19488
19489 public:
19492 using json_pointer = ::nlohmann::json_pointer<StringType>;
19493 template<typename T, typename SFINAE>
19494 using json_serializer = JSONSerializer<T, SFINAE>;
19500 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19501
19505
19507 // exceptions //
19509
19513
19520
19522
19524 // container types //
19526
19531
19534
19539
19541 using difference_type = std::ptrdiff_t;
19543 using size_type = std::size_t;
19544
19546 using allocator_type = AllocatorType<basic_json>;
19547
19549 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19551 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19552
19554 using iterator = iter_impl<basic_json>;
19556 using const_iterator = iter_impl<const basic_json>;
19558 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19560 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19561
19563
19567 {
19568 return allocator_type();
19569 }
19570
19575 {
19576 basic_json result;
19577
19578 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19579 result["name"] = "JSON for Modern C++";
19580 result["url"] = "https://github.com/nlohmann/json";
19581 result["version"]["string"] =
19582 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19583 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19584 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19585 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19586 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19587 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19588
19589#ifdef _WIN32
19590 result["platform"] = "win32";
19591#elif defined __linux__
19592 result["platform"] = "linux";
19593#elif defined __APPLE__
19594 result["platform"] = "apple";
19595#elif defined __unix__
19596 result["platform"] = "unix";
19597#else
19598 result["platform"] = "unknown";
19599#endif
19600
19601#if defined(__ICC) || defined(__INTEL_COMPILER)
19602 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19603#elif defined(__clang__)
19604 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19605#elif defined(__GNUC__) || defined(__GNUG__)
19606 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19607 std::to_string(__GNUC__), '.',
19608 std::to_string(__GNUC_MINOR__), '.',
19609 std::to_string(__GNUC_PATCHLEVEL__))
19610 }
19611 };
19612#elif defined(__HP_cc) || defined(__HP_aCC)
19613 result["compiler"] = "hp"
19614#elif defined(__IBMCPP__)
19615 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19616#elif defined(_MSC_VER)
19617 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19618#elif defined(__PGI)
19619 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19620#elif defined(__SUNPRO_CC)
19621 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19622#else
19623 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19624#endif
19625
19626#if defined(_MSVC_LANG)
19627 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19628#elif defined(__cplusplus)
19629 result["compiler"]["c++"] = std::to_string(__cplusplus);
19630#else
19631 result["compiler"]["c++"] = "unknown";
19632#endif
19633 return result;
19634 }
19635
19637 // JSON value data types //
19639
19644
19649#if defined(JSON_HAS_CPP_14)
19650 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19651 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19652 using default_object_comparator_t = std::less<>;
19653#else
19654 using default_object_comparator_t = std::less<StringType>;
19655#endif
19656
19659 using object_t = ObjectType<StringType,
19660 basic_json,
19662 AllocatorType<std::pair<const StringType,
19663 basic_json>>>;
19664
19667 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19668
19671 using string_t = StringType;
19672
19675 using boolean_t = BooleanType;
19676
19679 using number_integer_t = NumberIntegerType;
19680
19683 using number_unsigned_t = NumberUnsignedType;
19684
19687 using number_float_t = NumberFloatType;
19688
19691 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19692
19696
19698
19699 private:
19700
19702 template<typename T, typename... Args>
19704 static T* create(Args&& ... args)
19705 {
19706 AllocatorType<T> alloc;
19707 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19708
19709 auto deleter = [&](T * obj)
19710 {
19711 AllocatorTraits::deallocate(alloc, obj, 1);
19712 };
19713 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19714 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19715 JSON_ASSERT(obj != nullptr);
19716 return obj.release();
19717 }
19718
19720 // JSON value storage //
19722
19749 union json_value
19750 {
19754 array_t* array;
19756 string_t* string;
19758 binary_t* binary;
19760 boolean_t boolean;
19762 number_integer_t number_integer;
19764 number_unsigned_t number_unsigned;
19766 number_float_t number_float;
19767
19769 json_value() = default;
19771 json_value(boolean_t v) noexcept : boolean(v) {}
19773 json_value(number_integer_t v) noexcept : number_integer(v) {}
19775 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19777 json_value(number_float_t v) noexcept : number_float(v) {}
19779 json_value(value_t t)
19780 {
19781 switch (t)
19782 {
19783 case value_t::object:
19784 {
19785 object = create<object_t>();
19786 break;
19787 }
19788
19789 case value_t::array:
19790 {
19791 array = create<array_t>();
19792 break;
19793 }
19794
19795 case value_t::string:
19796 {
19797 string = create<string_t>("");
19798 break;
19799 }
19800
19801 case value_t::binary:
19802 {
19803 binary = create<binary_t>();
19804 break;
19805 }
19806
19807 case value_t::boolean:
19808 {
19809 boolean = static_cast<boolean_t>(false);
19810 break;
19811 }
19812
19813 case value_t::number_integer:
19814 {
19815 number_integer = static_cast<number_integer_t>(0);
19816 break;
19817 }
19818
19819 case value_t::number_unsigned:
19820 {
19821 number_unsigned = static_cast<number_unsigned_t>(0);
19822 break;
19823 }
19824
19825 case value_t::number_float:
19826 {
19827 number_float = static_cast<number_float_t>(0.0);
19828 break;
19829 }
19830
19831 case value_t::null:
19832 {
19833 object = nullptr; // silence warning, see #821
19834 break;
19835 }
19836
19837 case value_t::discarded:
19838 default:
19839 {
19840 object = nullptr; // silence warning, see #821
19841 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19842 {
19843 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19844 }
19845 break;
19846 }
19847 }
19848 }
19849
19851 json_value(const string_t& value) : string(create<string_t>(value)) {}
19852
19854 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19855
19857 json_value(const object_t& value) : object(create<object_t>(value)) {}
19858
19860 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19861
19863 json_value(const array_t& value) : array(create<array_t>(value)) {}
19864
19866 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19867
19869 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19870
19872 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19873
19875 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19876
19878 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19879
19880 void destroy(value_t t)
19881 {
19882 if (
19883 (t == value_t::object && object == nullptr) ||
19884 (t == value_t::array && array == nullptr) ||
19885 (t == value_t::string && string == nullptr) ||
19886 (t == value_t::binary && binary == nullptr)
19887 )
19888 {
19889 //not initialized (e.g. due to exception in the ctor)
19890 return;
19891 }
19892 if (t == value_t::array || t == value_t::object)
19893 {
19894 // flatten the current json_value to a heap-allocated stack
19895 std::vector<basic_json> stack;
19896
19897 // move the top-level items to stack
19898 if (t == value_t::array)
19899 {
19900 stack.reserve(array->size());
19901 std::move(array->begin(), array->end(), std::back_inserter(stack));
19902 }
19903 else
19904 {
19905 stack.reserve(object->size());
19906 for (auto&& it : *object)
19907 {
19908 stack.push_back(std::move(it.second));
19909 }
19910 }
19911
19912 while (!stack.empty())
19913 {
19914 // move the last item to local variable to be processed
19915 basic_json current_item(std::move(stack.back()));
19916 stack.pop_back();
19917
19918 // if current_item is array/object, move
19919 // its children to the stack to be processed later
19920 if (current_item.is_array())
19921 {
19922 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19923
19924 current_item.m_data.m_value.array->clear();
19925 }
19926 else if (current_item.is_object())
19927 {
19928 for (auto&& it : *current_item.m_data.m_value.object)
19929 {
19930 stack.push_back(std::move(it.second));
19931 }
19932
19933 current_item.m_data.m_value.object->clear();
19934 }
19935
19936 // it's now safe that current_item get destructed
19937 // since it doesn't have any children
19938 }
19939 }
19940
19941 switch (t)
19942 {
19943 case value_t::object:
19944 {
19945 AllocatorType<object_t> alloc;
19946 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19947 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19948 break;
19949 }
19950
19951 case value_t::array:
19952 {
19953 AllocatorType<array_t> alloc;
19954 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19955 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19956 break;
19957 }
19958
19959 case value_t::string:
19960 {
19961 AllocatorType<string_t> alloc;
19962 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19963 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19964 break;
19965 }
19966
19967 case value_t::binary:
19968 {
19969 AllocatorType<binary_t> alloc;
19970 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19971 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19972 break;
19973 }
19974
19975 case value_t::null:
19976 case value_t::boolean:
19977 case value_t::number_integer:
19978 case value_t::number_unsigned:
19979 case value_t::number_float:
19980 case value_t::discarded:
19981 default:
19982 {
19983 break;
19984 }
19985 }
19986 }
19987 };
19988
19989 private:
20008 void assert_invariant(bool check_parents = true) const noexcept
20009 {
20010 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20011 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20012 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20013 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20014
20015#if JSON_DIAGNOSTICS
20016 JSON_TRY
20017 {
20018 // cppcheck-suppress assertWithSideEffect
20019 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20020 {
20021 return j.m_parent == this;
20022 }));
20023 }
20024 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20025#endif
20026 static_cast<void>(check_parents);
20027 }
20028
20029 void set_parents()
20030 {
20031#if JSON_DIAGNOSTICS
20032 switch (m_data.m_type)
20033 {
20034 case value_t::array:
20035 {
20036 for (auto& element : *m_data.m_value.array)
20037 {
20038 element.m_parent = this;
20039 }
20040 break;
20041 }
20042
20043 case value_t::object:
20044 {
20045 for (auto& element : *m_data.m_value.object)
20046 {
20047 element.second.m_parent = this;
20048 }
20049 break;
20050 }
20051
20052 case value_t::null:
20053 case value_t::string:
20054 case value_t::boolean:
20055 case value_t::number_integer:
20056 case value_t::number_unsigned:
20057 case value_t::number_float:
20058 case value_t::binary:
20059 case value_t::discarded:
20060 default:
20061 break;
20062 }
20063#endif
20064 }
20065
20066 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20067 {
20068#if JSON_DIAGNOSTICS
20069 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20070 {
20071 (it + i)->m_parent = this;
20072 }
20073#else
20074 static_cast<void>(count_set_parents);
20075#endif
20076 return it;
20077 }
20078
20079 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20080 {
20081#if JSON_DIAGNOSTICS
20082 if (old_capacity != static_cast<std::size_t>(-1))
20083 {
20084 // see https://github.com/nlohmann/json/issues/2838
20085 JSON_ASSERT(type() == value_t::array);
20086 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20087 {
20088 // capacity has changed: update all parents
20089 set_parents();
20090 return j;
20091 }
20092 }
20093
20094 // ordered_json uses a vector internally, so pointers could have
20095 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20096#ifdef JSON_HEDLEY_MSVC_VERSION
20097#pragma warning(push )
20098#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20099#endif
20101 {
20102 set_parents();
20103 return j;
20104 }
20105#ifdef JSON_HEDLEY_MSVC_VERSION
20106#pragma warning( pop )
20107#endif
20108
20109 j.m_parent = this;
20110#else
20111 static_cast<void>(j);
20112 static_cast<void>(old_capacity);
20113#endif
20114 return j;
20115 }
20116
20117 public:
20119 // JSON parser callback //
20121
20125
20129
20131 // constructors //
20133
20138
20142 : m_data(v)
20143 {
20144 assert_invariant();
20145 }
20146
20149 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20150 : basic_json(value_t::null)
20151 {
20152 assert_invariant();
20153 }
20154
20157 template < typename CompatibleType,
20161 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20162 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20163 std::forward<CompatibleType>(val))))
20164 {
20165 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20166 set_parents();
20167 assert_invariant();
20168 }
20169
20172 template < typename BasicJsonType,
20174 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20175 basic_json(const BasicJsonType& val)
20176 {
20177 using other_boolean_t = typename BasicJsonType::boolean_t;
20178 using other_number_float_t = typename BasicJsonType::number_float_t;
20179 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20180 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20181 using other_string_t = typename BasicJsonType::string_t;
20182 using other_object_t = typename BasicJsonType::object_t;
20183 using other_array_t = typename BasicJsonType::array_t;
20184 using other_binary_t = typename BasicJsonType::binary_t;
20185
20186 switch (val.type())
20187 {
20188 case value_t::boolean:
20189 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20190 break;
20191 case value_t::number_float:
20192 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20193 break;
20194 case value_t::number_integer:
20195 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20196 break;
20197 case value_t::number_unsigned:
20198 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20199 break;
20200 case value_t::string:
20201 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20202 break;
20203 case value_t::object:
20204 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20205 break;
20206 case value_t::array:
20207 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20208 break;
20209 case value_t::binary:
20210 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20211 break;
20212 case value_t::null:
20213 *this = nullptr;
20214 break;
20215 case value_t::discarded:
20216 m_data.m_type = value_t::discarded;
20217 break;
20218 default: // LCOV_EXCL_LINE
20219 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20220 }
20221 JSON_ASSERT(m_data.m_type == val.type());
20222 set_parents();
20223 assert_invariant();
20224 }
20225
20229 bool type_deduction = true,
20230 value_t manual_type = value_t::array)
20231 {
20232 // check if each element is an array with two elements whose first
20233 // element is a string
20234 bool is_an_object = std::all_of(init.begin(), init.end(),
20235 [](const detail::json_ref<basic_json>& element_ref)
20236 {
20237 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20238 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20239 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20240 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20241 });
20242
20243 // adjust type if type deduction is not wanted
20244 if (!type_deduction)
20245 {
20246 // if array is wanted, do not create an object though possible
20247 if (manual_type == value_t::array)
20248 {
20249 is_an_object = false;
20250 }
20251
20252 // if object is wanted but impossible, throw an exception
20253 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20254 {
20255 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20256 }
20257 }
20258
20259 if (is_an_object)
20260 {
20261 // the initializer list is a list of pairs -> create object
20262 m_data.m_type = value_t::object;
20263 m_data.m_value = value_t::object;
20264
20265 for (auto& element_ref : init)
20266 {
20267 auto element = element_ref.moved_or_copied();
20268 m_data.m_value.object->emplace(
20269 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20270 std::move((*element.m_data.m_value.array)[1]));
20271 }
20272 }
20273 else
20274 {
20275 // the initializer list describes an array -> create array
20276 m_data.m_type = value_t::array;
20277 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20278 }
20279
20280 set_parents();
20281 assert_invariant();
20282 }
20283
20287 static basic_json binary(const typename binary_t::container_type& init)
20288 {
20289 auto res = basic_json();
20290 res.m_data.m_type = value_t::binary;
20291 res.m_data.m_value = init;
20292 return res;
20293 }
20294
20298 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20299 {
20300 auto res = basic_json();
20301 res.m_data.m_type = value_t::binary;
20302 res.m_data.m_value = binary_t(init, subtype);
20303 return res;
20304 }
20305
20309 static basic_json binary(typename binary_t::container_type&& init)
20310 {
20311 auto res = basic_json();
20312 res.m_data.m_type = value_t::binary;
20313 res.m_data.m_value = std::move(init);
20314 return res;
20315 }
20316
20320 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20321 {
20322 auto res = basic_json();
20323 res.m_data.m_type = value_t::binary;
20324 res.m_data.m_value = binary_t(std::move(init), subtype);
20325 return res;
20326 }
20327
20332 {
20333 return basic_json(init, false, value_t::array);
20334 }
20335
20340 {
20341 return basic_json(init, false, value_t::object);
20342 }
20343
20347 m_data{cnt, val}
20348 {
20349 set_parents();
20350 assert_invariant();
20351 }
20352
20355 template < class InputIT, typename std::enable_if <
20356 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20357 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20358 basic_json(InputIT first, InputIT last)
20359 {
20360 JSON_ASSERT(first.m_object != nullptr);
20361 JSON_ASSERT(last.m_object != nullptr);
20362
20363 // make sure iterator fits the current value
20364 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20365 {
20366 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20367 }
20368
20369 // copy type from first iterator
20370 m_data.m_type = first.m_object->m_data.m_type;
20371
20372 // check if iterator range is complete for primitive values
20373 switch (m_data.m_type)
20374 {
20375 case value_t::boolean:
20376 case value_t::number_float:
20377 case value_t::number_integer:
20378 case value_t::number_unsigned:
20379 case value_t::string:
20380 {
20381 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20382 || !last.m_it.primitive_iterator.is_end()))
20383 {
20384 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20385 }
20386 break;
20387 }
20388
20389 case value_t::null:
20390 case value_t::object:
20391 case value_t::array:
20392 case value_t::binary:
20393 case value_t::discarded:
20394 default:
20395 break;
20396 }
20397
20398 switch (m_data.m_type)
20399 {
20400 case value_t::number_integer:
20401 {
20402 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20403 break;
20404 }
20405
20406 case value_t::number_unsigned:
20407 {
20408 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20409 break;
20410 }
20411
20412 case value_t::number_float:
20413 {
20414 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20415 break;
20416 }
20417
20418 case value_t::boolean:
20419 {
20420 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20421 break;
20422 }
20423
20424 case value_t::string:
20425 {
20426 m_data.m_value = *first.m_object->m_data.m_value.string;
20427 break;
20428 }
20429
20430 case value_t::object:
20431 {
20432 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20433 last.m_it.object_iterator);
20434 break;
20435 }
20436
20437 case value_t::array:
20438 {
20439 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20440 last.m_it.array_iterator);
20441 break;
20442 }
20443
20444 case value_t::binary:
20445 {
20446 m_data.m_value = *first.m_object->m_data.m_value.binary;
20447 break;
20448 }
20449
20450 case value_t::null:
20451 case value_t::discarded:
20452 default:
20453 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20454 }
20455
20456 set_parents();
20457 assert_invariant();
20458 }
20459
20461 // other constructors and destructor //
20463
20464 template<typename JsonRef,
20466 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20467 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20468
20472 : json_base_class_t(other)
20473 {
20474 m_data.m_type = other.m_data.m_type;
20475 // check of passed value is valid
20476 other.assert_invariant();
20477
20478 switch (m_data.m_type)
20479 {
20480 case value_t::object:
20481 {
20482 m_data.m_value = *other.m_data.m_value.object;
20483 break;
20484 }
20485
20486 case value_t::array:
20487 {
20488 m_data.m_value = *other.m_data.m_value.array;
20489 break;
20490 }
20491
20492 case value_t::string:
20493 {
20494 m_data.m_value = *other.m_data.m_value.string;
20495 break;
20496 }
20497
20498 case value_t::boolean:
20499 {
20500 m_data.m_value = other.m_data.m_value.boolean;
20501 break;
20502 }
20503
20504 case value_t::number_integer:
20505 {
20506 m_data.m_value = other.m_data.m_value.number_integer;
20507 break;
20508 }
20509
20510 case value_t::number_unsigned:
20511 {
20512 m_data.m_value = other.m_data.m_value.number_unsigned;
20513 break;
20514 }
20515
20516 case value_t::number_float:
20517 {
20518 m_data.m_value = other.m_data.m_value.number_float;
20519 break;
20520 }
20521
20522 case value_t::binary:
20523 {
20524 m_data.m_value = *other.m_data.m_value.binary;
20525 break;
20526 }
20527
20528 case value_t::null:
20529 case value_t::discarded:
20530 default:
20531 break;
20532 }
20533
20534 set_parents();
20535 assert_invariant();
20536 }
20537
20540 basic_json(basic_json&& other) noexcept
20541 : json_base_class_t(std::forward<json_base_class_t>(other)),
20542 m_data(std::move(other.m_data))
20543 {
20544 // check that passed value is valid
20545 other.assert_invariant(false);
20546
20547 // invalidate payload
20548 other.m_data.m_type = value_t::null;
20549 other.m_data.m_value = {};
20550
20551 set_parents();
20552 assert_invariant();
20553 }
20554
20558 std::is_nothrow_move_constructible<value_t>::value&&
20559 std::is_nothrow_move_assignable<value_t>::value&&
20560 std::is_nothrow_move_constructible<json_value>::value&&
20561 std::is_nothrow_move_assignable<json_value>::value&&
20562 std::is_nothrow_move_assignable<json_base_class_t>::value
20563 )
20564 {
20565 // check that passed value is valid
20566 other.assert_invariant();
20567
20568 using std::swap;
20569 swap(m_data.m_type, other.m_data.m_type);
20570 swap(m_data.m_value, other.m_data.m_value);
20571 json_base_class_t::operator=(std::move(other));
20572
20573 set_parents();
20574 assert_invariant();
20575 return *this;
20576 }
20577
20580 ~basic_json() noexcept
20581 {
20582 assert_invariant(false);
20583 }
20584
20586
20587 public:
20589 // object inspection //
20591
20595
20598 string_t dump(const int indent = -1,
20599 const char indent_char = ' ',
20600 const bool ensure_ascii = false,
20601 const error_handler_t error_handler = error_handler_t::strict) const
20602 {
20603 string_t result;
20604 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20605
20606 if (indent >= 0)
20607 {
20608 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20609 }
20610 else
20611 {
20612 s.dump(*this, false, ensure_ascii, 0);
20613 }
20614
20615 return result;
20616 }
20617
20620 constexpr value_t type() const noexcept
20621 {
20622 return m_data.m_type;
20623 }
20624
20627 constexpr bool is_primitive() const noexcept
20628 {
20629 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20630 }
20631
20634 constexpr bool is_structured() const noexcept
20635 {
20636 return is_array() || is_object();
20637 }
20638
20641 constexpr bool is_null() const noexcept
20642 {
20643 return m_data.m_type == value_t::null;
20644 }
20645
20648 constexpr bool is_boolean() const noexcept
20649 {
20650 return m_data.m_type == value_t::boolean;
20651 }
20652
20655 constexpr bool is_number() const noexcept
20656 {
20657 return is_number_integer() || is_number_float();
20658 }
20659
20662 constexpr bool is_number_integer() const noexcept
20663 {
20664 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20665 }
20666
20669 constexpr bool is_number_unsigned() const noexcept
20670 {
20671 return m_data.m_type == value_t::number_unsigned;
20672 }
20673
20676 constexpr bool is_number_float() const noexcept
20677 {
20678 return m_data.m_type == value_t::number_float;
20679 }
20680
20683 constexpr bool is_object() const noexcept
20684 {
20685 return m_data.m_type == value_t::object;
20686 }
20687
20690 constexpr bool is_array() const noexcept
20691 {
20692 return m_data.m_type == value_t::array;
20693 }
20694
20697 constexpr bool is_string() const noexcept
20698 {
20699 return m_data.m_type == value_t::string;
20700 }
20701
20704 constexpr bool is_binary() const noexcept
20705 {
20706 return m_data.m_type == value_t::binary;
20707 }
20708
20711 constexpr bool is_discarded() const noexcept
20712 {
20713 return m_data.m_type == value_t::discarded;
20714 }
20715
20718 constexpr operator value_t() const noexcept
20719 {
20720 return m_data.m_type;
20721 }
20722
20724
20725 private:
20727 // value access //
20729
20731 boolean_t get_impl(boolean_t* /*unused*/) const
20732 {
20733 if (JSON_HEDLEY_LIKELY(is_boolean()))
20734 {
20735 return m_data.m_value.boolean;
20736 }
20737
20738 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20739 }
20740
20742 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20743 {
20744 return is_object() ? m_data.m_value.object : nullptr;
20745 }
20746
20748 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20749 {
20750 return is_object() ? m_data.m_value.object : nullptr;
20751 }
20752
20754 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20755 {
20756 return is_array() ? m_data.m_value.array : nullptr;
20757 }
20758
20760 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20761 {
20762 return is_array() ? m_data.m_value.array : nullptr;
20763 }
20764
20766 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20767 {
20768 return is_string() ? m_data.m_value.string : nullptr;
20769 }
20770
20772 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20773 {
20774 return is_string() ? m_data.m_value.string : nullptr;
20775 }
20776
20778 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20779 {
20780 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20781 }
20782
20784 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20785 {
20786 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20787 }
20788
20790 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20791 {
20792 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20793 }
20794
20796 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20797 {
20798 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20799 }
20800
20802 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20803 {
20804 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20805 }
20806
20808 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20809 {
20810 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20811 }
20812
20814 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20815 {
20816 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20817 }
20818
20820 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20821 {
20822 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20823 }
20824
20826 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20827 {
20828 return is_binary() ? m_data.m_value.binary : nullptr;
20829 }
20830
20832 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20833 {
20834 return is_binary() ? m_data.m_value.binary : nullptr;
20835 }
20836
20848 template<typename ReferenceType, typename ThisType>
20849 static ReferenceType get_ref_impl(ThisType& obj)
20850 {
20851 // delegate the call to get_ptr<>()
20852 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20853
20854 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20855 {
20856 return *ptr;
20857 }
20858
20859 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20860 }
20861
20862 public:
20866
20869 template<typename PointerType, typename std::enable_if<
20870 std::is_pointer<PointerType>::value, int>::type = 0>
20871 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20872 {
20873 // delegate the call to get_impl_ptr<>()
20874 return get_impl_ptr(static_cast<PointerType>(nullptr));
20875 }
20876
20879 template < typename PointerType, typename std::enable_if <
20880 std::is_pointer<PointerType>::value&&
20881 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20882 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20883 {
20884 // delegate the call to get_impl_ptr<>() const
20885 return get_impl_ptr(static_cast<PointerType>(nullptr));
20886 }
20887
20888 private:
20927 template < typename ValueType,
20931 int > = 0 >
20932 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20933 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20934 {
20935 auto ret = ValueType();
20936 JSONSerializer<ValueType>::from_json(*this, ret);
20937 return ret;
20938 }
20939
20970 template < typename ValueType,
20973 int > = 0 >
20974 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20975 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20976 {
20977 return JSONSerializer<ValueType>::from_json(*this);
20978 }
20979
20995 template < typename BasicJsonType,
20998 int > = 0 >
20999 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21000 {
21001 return *this;
21002 }
21003
21018 template<typename BasicJsonType,
21020 std::is_same<BasicJsonType, basic_json_t>::value,
21021 int> = 0>
21022 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21023 {
21024 return *this;
21025 }
21026
21031 template<typename PointerType,
21033 std::is_pointer<PointerType>::value,
21034 int> = 0>
21035 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21036 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21037 {
21038 // delegate the call to get_ptr
21039 return get_ptr<PointerType>();
21040 }
21041
21042 public:
21066 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21067#if defined(JSON_HAS_CPP_14)
21068 constexpr
21069#endif
21070 auto get() const noexcept(
21071 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21072 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21073 {
21074 // we cannot static_assert on ValueTypeCV being non-const, because
21075 // there is support for get<const basic_json_t>(), which is why we
21076 // still need the uncvref
21077 static_assert(!std::is_reference<ValueTypeCV>::value,
21078 "get() cannot be used with reference types, you might want to use get_ref()");
21079 return get_impl<ValueType>(detail::priority_tag<4> {});
21080 }
21081
21109 template<typename PointerType, typename std::enable_if<
21110 std::is_pointer<PointerType>::value, int>::type = 0>
21111 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21112 {
21113 // delegate the call to get_ptr
21114 return get_ptr<PointerType>();
21115 }
21116
21119 template < typename ValueType,
21123 int > = 0 >
21124 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21125 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21126 {
21127 JSONSerializer<ValueType>::from_json(*this, v);
21128 return v;
21129 }
21130
21131 // specialization to allow calling get_to with a basic_json value
21132 // see https://github.com/nlohmann/json/issues/2175
21133 template<typename ValueType,
21136 int> = 0>
21137 ValueType & get_to(ValueType& v) const
21138 {
21139 v = *this;
21140 return v;
21141 }
21142
21143 template <
21144 typename T, std::size_t N,
21145 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21148 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21149 noexcept(noexcept(JSONSerializer<Array>::from_json(
21150 std::declval<const basic_json_t&>(), v)))
21151 {
21152 JSONSerializer<Array>::from_json(*this, v);
21153 return v;
21154 }
21155
21158 template<typename ReferenceType, typename std::enable_if<
21159 std::is_reference<ReferenceType>::value, int>::type = 0>
21160 ReferenceType get_ref()
21161 {
21162 // delegate call to get_ref_impl
21163 return get_ref_impl<ReferenceType>(*this);
21164 }
21165
21168 template < typename ReferenceType, typename std::enable_if <
21169 std::is_reference<ReferenceType>::value&&
21170 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21171 ReferenceType get_ref() const
21172 {
21173 // delegate call to get_ref_impl
21174 return get_ref_impl<ReferenceType>(*this);
21175 }
21176
21206 template < typename ValueType, typename std::enable_if <
21214#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21216#endif
21217#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21219#endif
21221 >::value, int >::type = 0 >
21222 JSON_EXPLICIT operator ValueType() const
21223 {
21224 // delegate the call to get<>() const
21225 return get<ValueType>();
21226 }
21227
21231 {
21232 if (!is_binary())
21233 {
21234 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21235 }
21236
21237 return *get_ptr<binary_t*>();
21238 }
21239
21242 const binary_t& get_binary() const
21243 {
21244 if (!is_binary())
21245 {
21246 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21247 }
21248
21249 return *get_ptr<const binary_t*>();
21250 }
21251
21253
21255 // element access //
21257
21261
21265 {
21266 // at only works for arrays
21267 if (JSON_HEDLEY_LIKELY(is_array()))
21268 {
21269 JSON_TRY
21270 {
21271 return set_parent(m_data.m_value.array->at(idx));
21272 }
21273 JSON_CATCH (std::out_of_range&)
21274 {
21275 // create better exception explanation
21276 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21277 }
21278 }
21279 else
21280 {
21281 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21282 }
21283 }
21284
21288 {
21289 // at only works for arrays
21290 if (JSON_HEDLEY_LIKELY(is_array()))
21291 {
21292 JSON_TRY
21293 {
21294 return m_data.m_value.array->at(idx);
21295 }
21296 JSON_CATCH (std::out_of_range&)
21297 {
21298 // create better exception explanation
21299 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21300 }
21301 }
21302 else
21303 {
21304 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21305 }
21306 }
21307
21310 reference at(const typename object_t::key_type& key)
21311 {
21312 // at only works for objects
21313 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21314 {
21315 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21316 }
21317
21318 auto it = m_data.m_value.object->find(key);
21319 if (it == m_data.m_value.object->end())
21320 {
21321 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21322 }
21323 return set_parent(it->second);
21324 }
21325
21328 template<class KeyType, detail::enable_if_t<
21330 reference at(KeyType && key)
21331 {
21332 // at only works for objects
21333 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21334 {
21335 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21336 }
21337
21338 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21339 if (it == m_data.m_value.object->end())
21340 {
21341 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21342 }
21343 return set_parent(it->second);
21344 }
21345
21348 const_reference at(const typename object_t::key_type& key) const
21349 {
21350 // at only works for objects
21351 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21352 {
21353 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21354 }
21355
21356 auto it = m_data.m_value.object->find(key);
21357 if (it == m_data.m_value.object->end())
21358 {
21359 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21360 }
21361 return it->second;
21362 }
21363
21366 template<class KeyType, detail::enable_if_t<
21368 const_reference at(KeyType && key) const
21369 {
21370 // at only works for objects
21371 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21372 {
21373 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21374 }
21375
21376 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21377 if (it == m_data.m_value.object->end())
21378 {
21379 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21380 }
21381 return it->second;
21382 }
21383
21387 {
21388 // implicitly convert null value to an empty array
21389 if (is_null())
21390 {
21391 m_data.m_type = value_t::array;
21392 m_data.m_value.array = create<array_t>();
21393 assert_invariant();
21394 }
21395
21396 // operator[] only works for arrays
21397 if (JSON_HEDLEY_LIKELY(is_array()))
21398 {
21399 // fill up array with null values if given idx is outside range
21400 if (idx >= m_data.m_value.array->size())
21401 {
21402#if JSON_DIAGNOSTICS
21403 // remember array size & capacity before resizing
21404 const auto old_size = m_data.m_value.array->size();
21405 const auto old_capacity = m_data.m_value.array->capacity();
21406#endif
21407 m_data.m_value.array->resize(idx + 1);
21408
21409#if JSON_DIAGNOSTICS
21410 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21411 {
21412 // capacity has changed: update all parents
21413 set_parents();
21414 }
21415 else
21416 {
21417 // set parent for values added above
21418 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21419 }
21420#endif
21421 assert_invariant();
21422 }
21423
21424 return m_data.m_value.array->operator[](idx);
21425 }
21426
21427 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21428 }
21429
21433 {
21434 // const operator[] only works for arrays
21435 if (JSON_HEDLEY_LIKELY(is_array()))
21436 {
21437 return m_data.m_value.array->operator[](idx);
21438 }
21439
21440 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21441 }
21442
21445 reference operator[](typename object_t::key_type key)
21446 {
21447 // implicitly convert null value to an empty object
21448 if (is_null())
21449 {
21450 m_data.m_type = value_t::object;
21451 m_data.m_value.object = create<object_t>();
21452 assert_invariant();
21453 }
21454
21455 // operator[] only works for objects
21456 if (JSON_HEDLEY_LIKELY(is_object()))
21457 {
21458 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21459 return set_parent(result.first->second);
21460 }
21461
21462 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21463 }
21464
21467 const_reference operator[](const typename object_t::key_type& key) const
21468 {
21469 // const operator[] only works for objects
21470 if (JSON_HEDLEY_LIKELY(is_object()))
21471 {
21472 auto it = m_data.m_value.object->find(key);
21473 JSON_ASSERT(it != m_data.m_value.object->end());
21474 return it->second;
21475 }
21476
21477 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21478 }
21479
21480 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21481 // (they seemingly cannot be constrained to resolve the ambiguity)
21482 template<typename T>
21484 {
21485 return operator[](typename object_t::key_type(key));
21486 }
21487
21488 template<typename T>
21490 {
21491 return operator[](typename object_t::key_type(key));
21492 }
21493
21496 template<class KeyType, detail::enable_if_t<
21498 reference operator[](KeyType && key)
21499 {
21500 // implicitly convert null value to an empty object
21501 if (is_null())
21502 {
21503 m_data.m_type = value_t::object;
21504 m_data.m_value.object = create<object_t>();
21505 assert_invariant();
21506 }
21507
21508 // operator[] only works for objects
21509 if (JSON_HEDLEY_LIKELY(is_object()))
21510 {
21511 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21512 return set_parent(result.first->second);
21513 }
21514
21515 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21516 }
21517
21520 template<class KeyType, detail::enable_if_t<
21522 const_reference operator[](KeyType && key) const
21523 {
21524 // const operator[] only works for objects
21525 if (JSON_HEDLEY_LIKELY(is_object()))
21526 {
21527 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21528 JSON_ASSERT(it != m_data.m_value.object->end());
21529 return it->second;
21530 }
21531
21532 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21533 }
21534
21535 private:
21536 template<typename KeyType>
21537 using is_comparable_with_object_key = detail::is_comparable <
21538 object_comparator_t, const typename object_t::key_type&, KeyType >;
21539
21540 template<typename ValueType>
21541 using value_return_type = std::conditional <
21543 string_t, typename std::decay<ValueType>::type >;
21544
21545 public:
21548 template < class ValueType, detail::enable_if_t <
21551 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21552 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21553 {
21554 // value only works for objects
21555 if (JSON_HEDLEY_LIKELY(is_object()))
21556 {
21557 // if key is found, return value and given default value otherwise
21558 const auto it = find(key);
21559 if (it != end())
21560 {
21561 return it->template get<ValueType>();
21562 }
21563
21564 return default_value;
21565 }
21566
21567 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21568 }
21569
21572 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21576 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21577 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21578 {
21579 // value only works for objects
21580 if (JSON_HEDLEY_LIKELY(is_object()))
21581 {
21582 // if key is found, return value and given default value otherwise
21583 const auto it = find(key);
21584 if (it != end())
21585 {
21586 return it->template get<ReturnType>();
21587 }
21588
21589 return std::forward<ValueType>(default_value);
21590 }
21591
21592 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21593 }
21594
21597 template < class ValueType, class KeyType, detail::enable_if_t <
21600 && is_comparable_with_object_key<KeyType>::value
21602 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21603 ValueType value(KeyType && key, const ValueType& default_value) const
21604 {
21605 // value only works for objects
21606 if (JSON_HEDLEY_LIKELY(is_object()))
21607 {
21608 // if key is found, return value and given default value otherwise
21609 const auto it = find(std::forward<KeyType>(key));
21610 if (it != end())
21611 {
21612 return it->template get<ValueType>();
21613 }
21614
21615 return default_value;
21616 }
21617
21618 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21619 }
21620
21623 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21627 && is_comparable_with_object_key<KeyType>::value
21629 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21630 ReturnType value(KeyType && key, ValueType && default_value) const
21631 {
21632 // value only works for objects
21633 if (JSON_HEDLEY_LIKELY(is_object()))
21634 {
21635 // if key is found, return value and given default value otherwise
21636 const auto it = find(std::forward<KeyType>(key));
21637 if (it != end())
21638 {
21639 return it->template get<ReturnType>();
21640 }
21641
21642 return std::forward<ValueType>(default_value);
21643 }
21644
21645 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21646 }
21647
21650 template < class ValueType, detail::enable_if_t <
21652 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21653 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21654 {
21655 // value only works for objects
21656 if (JSON_HEDLEY_LIKELY(is_object()))
21657 {
21658 // if pointer resolves a value, return it or use default value
21659 JSON_TRY
21660 {
21661 return ptr.get_checked(this).template get<ValueType>();
21662 }
21664 {
21665 return default_value;
21666 }
21667 }
21668
21669 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21670 }
21671
21674 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21677 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21678 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21679 {
21680 // value only works for objects
21681 if (JSON_HEDLEY_LIKELY(is_object()))
21682 {
21683 // if pointer resolves a value, return it or use default value
21684 JSON_TRY
21685 {
21686 return ptr.get_checked(this).template get<ReturnType>();
21687 }
21689 {
21690 return std::forward<ValueType>(default_value);
21691 }
21692 }
21693
21694 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21695 }
21696
21697 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21700 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21701 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21702 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21703 {
21704 return value(ptr.convert(), default_value);
21705 }
21706
21707 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21711 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21712 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21713 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21714 {
21715 return value(ptr.convert(), std::forward<ValueType>(default_value));
21716 }
21717
21721 {
21722 return *begin();
21723 }
21724
21728 {
21729 return *cbegin();
21730 }
21731
21735 {
21736 auto tmp = end();
21737 --tmp;
21738 return *tmp;
21739 }
21740
21744 {
21745 auto tmp = cend();
21746 --tmp;
21747 return *tmp;
21748 }
21749
21752 template < class IteratorType, detail::enable_if_t <
21753 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21754 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21755 IteratorType erase(IteratorType pos)
21756 {
21757 // make sure iterator fits the current value
21758 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21759 {
21760 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21761 }
21762
21763 IteratorType result = end();
21764
21765 switch (m_data.m_type)
21766 {
21767 case value_t::boolean:
21768 case value_t::number_float:
21769 case value_t::number_integer:
21770 case value_t::number_unsigned:
21771 case value_t::string:
21772 case value_t::binary:
21773 {
21774 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21775 {
21776 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21777 }
21778
21779 if (is_string())
21780 {
21781 AllocatorType<string_t> alloc;
21782 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21783 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21784 m_data.m_value.string = nullptr;
21785 }
21786 else if (is_binary())
21787 {
21788 AllocatorType<binary_t> alloc;
21789 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21790 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21791 m_data.m_value.binary = nullptr;
21792 }
21793
21794 m_data.m_type = value_t::null;
21795 assert_invariant();
21796 break;
21797 }
21798
21799 case value_t::object:
21800 {
21801 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21802 break;
21803 }
21804
21805 case value_t::array:
21806 {
21807 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21808 break;
21809 }
21810
21811 case value_t::null:
21812 case value_t::discarded:
21813 default:
21814 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21815 }
21816
21817 return result;
21818 }
21819
21822 template < class IteratorType, detail::enable_if_t <
21823 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21824 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21825 IteratorType erase(IteratorType first, IteratorType last)
21826 {
21827 // make sure iterator fits the current value
21828 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21829 {
21830 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21831 }
21832
21833 IteratorType result = end();
21834
21835 switch (m_data.m_type)
21836 {
21837 case value_t::boolean:
21838 case value_t::number_float:
21839 case value_t::number_integer:
21840 case value_t::number_unsigned:
21841 case value_t::string:
21842 case value_t::binary:
21843 {
21844 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21845 || !last.m_it.primitive_iterator.is_end()))
21846 {
21847 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21848 }
21849
21850 if (is_string())
21851 {
21852 AllocatorType<string_t> alloc;
21853 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21854 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21855 m_data.m_value.string = nullptr;
21856 }
21857 else if (is_binary())
21858 {
21859 AllocatorType<binary_t> alloc;
21860 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21861 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21862 m_data.m_value.binary = nullptr;
21863 }
21864
21865 m_data.m_type = value_t::null;
21866 assert_invariant();
21867 break;
21868 }
21869
21870 case value_t::object:
21871 {
21872 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21873 last.m_it.object_iterator);
21874 break;
21875 }
21876
21877 case value_t::array:
21878 {
21879 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21880 last.m_it.array_iterator);
21881 break;
21882 }
21883
21884 case value_t::null:
21885 case value_t::discarded:
21886 default:
21887 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21888 }
21889
21890 return result;
21891 }
21892
21893 private:
21894 template < typename KeyType, detail::enable_if_t <
21896 size_type erase_internal(KeyType && key)
21897 {
21898 // this erase only works for objects
21899 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21900 {
21901 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21902 }
21903
21904 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21905 }
21906
21907 template < typename KeyType, detail::enable_if_t <
21909 size_type erase_internal(KeyType && key)
21910 {
21911 // this erase only works for objects
21912 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21913 {
21914 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21915 }
21916
21917 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21918 if (it != m_data.m_value.object->end())
21919 {
21920 m_data.m_value.object->erase(it);
21921 return 1;
21922 }
21923 return 0;
21924 }
21925
21926 public:
21927
21930 size_type erase(const typename object_t::key_type& key)
21931 {
21932 // the indirection via erase_internal() is added to avoid making this
21933 // function a template and thus de-rank it during overload resolution
21934 return erase_internal(key);
21935 }
21936
21939 template<class KeyType, detail::enable_if_t<
21941 size_type erase(KeyType && key)
21942 {
21943 return erase_internal(std::forward<KeyType>(key));
21944 }
21945
21948 void erase(const size_type idx)
21949 {
21950 // this erase only works for arrays
21951 if (JSON_HEDLEY_LIKELY(is_array()))
21952 {
21953 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21954 {
21955 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21956 }
21957
21958 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21959 }
21960 else
21961 {
21962 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21963 }
21964 }
21965
21967
21969 // lookup //
21971
21974
21977 iterator find(const typename object_t::key_type& key)
21978 {
21979 auto result = end();
21980
21981 if (is_object())
21982 {
21983 result.m_it.object_iterator = m_data.m_value.object->find(key);
21984 }
21985
21986 return result;
21987 }
21988
21991 const_iterator find(const typename object_t::key_type& key) const
21992 {
21993 auto result = cend();
21994
21995 if (is_object())
21996 {
21997 result.m_it.object_iterator = m_data.m_value.object->find(key);
21998 }
21999
22000 return result;
22001 }
22002
22005 template<class KeyType, detail::enable_if_t<
22007 iterator find(KeyType && key)
22008 {
22009 auto result = end();
22010
22011 if (is_object())
22012 {
22013 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22014 }
22015
22016 return result;
22017 }
22018
22021 template<class KeyType, detail::enable_if_t<
22023 const_iterator find(KeyType && key) const
22024 {
22025 auto result = cend();
22026
22027 if (is_object())
22028 {
22029 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22030 }
22031
22032 return result;
22033 }
22034
22037 size_type count(const typename object_t::key_type& key) const
22038 {
22039 // return 0 for all nonobject types
22040 return is_object() ? m_data.m_value.object->count(key) : 0;
22041 }
22042
22045 template<class KeyType, detail::enable_if_t<
22047 size_type count(KeyType && key) const
22048 {
22049 // return 0 for all nonobject types
22050 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22051 }
22052
22055 bool contains(const typename object_t::key_type& key) const
22056 {
22057 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22058 }
22059
22062 template<class KeyType, detail::enable_if_t<
22064 bool contains(KeyType && key) const
22065 {
22066 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22067 }
22068
22071 bool contains(const json_pointer& ptr) const
22072 {
22073 return ptr.contains(this);
22074 }
22075
22076 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22077 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22078 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22079 {
22080 return ptr.contains(this);
22081 }
22082
22084
22086 // iterators //
22088
22091
22094 iterator begin() noexcept
22095 {
22096 iterator result(this);
22097 result.set_begin();
22098 return result;
22099 }
22100
22103 const_iterator begin() const noexcept
22104 {
22105 return cbegin();
22106 }
22107
22110 const_iterator cbegin() const noexcept
22111 {
22112 const_iterator result(this);
22113 result.set_begin();
22114 return result;
22115 }
22116
22119 iterator end() noexcept
22120 {
22121 iterator result(this);
22122 result.set_end();
22123 return result;
22124 }
22125
22128 const_iterator end() const noexcept
22129 {
22130 return cend();
22131 }
22132
22135 const_iterator cend() const noexcept
22136 {
22137 const_iterator result(this);
22138 result.set_end();
22139 return result;
22140 }
22141
22145 {
22146 return reverse_iterator(end());
22147 }
22148
22152 {
22153 return crbegin();
22154 }
22155
22159 {
22160 return reverse_iterator(begin());
22161 }
22162
22166 {
22167 return crend();
22168 }
22169
22173 {
22174 return const_reverse_iterator(cend());
22175 }
22176
22180 {
22181 return const_reverse_iterator(cbegin());
22182 }
22183
22184 public:
22190 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22191 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22192 {
22193 return ref.items();
22194 }
22195
22201 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22202 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22203 {
22204 return ref.items();
22205 }
22206
22209 iteration_proxy<iterator> items() noexcept
22210 {
22211 return iteration_proxy<iterator>(*this);
22212 }
22213
22216 iteration_proxy<const_iterator> items() const noexcept
22217 {
22218 return iteration_proxy<const_iterator>(*this);
22219 }
22220
22222
22224 // capacity //
22226
22229
22232 bool empty() const noexcept
22233 {
22234 switch (m_data.m_type)
22235 {
22236 case value_t::null:
22237 {
22238 // null values are empty
22239 return true;
22240 }
22241
22242 case value_t::array:
22243 {
22244 // delegate call to array_t::empty()
22245 return m_data.m_value.array->empty();
22246 }
22247
22248 case value_t::object:
22249 {
22250 // delegate call to object_t::empty()
22251 return m_data.m_value.object->empty();
22252 }
22253
22254 case value_t::string:
22255 case value_t::boolean:
22256 case value_t::number_integer:
22257 case value_t::number_unsigned:
22258 case value_t::number_float:
22259 case value_t::binary:
22260 case value_t::discarded:
22261 default:
22262 {
22263 // all other types are nonempty
22264 return false;
22265 }
22266 }
22267 }
22268
22271 size_type size() const noexcept
22272 {
22273 switch (m_data.m_type)
22274 {
22275 case value_t::null:
22276 {
22277 // null values are empty
22278 return 0;
22279 }
22280
22281 case value_t::array:
22282 {
22283 // delegate call to array_t::size()
22284 return m_data.m_value.array->size();
22285 }
22286
22287 case value_t::object:
22288 {
22289 // delegate call to object_t::size()
22290 return m_data.m_value.object->size();
22291 }
22292
22293 case value_t::string:
22294 case value_t::boolean:
22295 case value_t::number_integer:
22296 case value_t::number_unsigned:
22297 case value_t::number_float:
22298 case value_t::binary:
22299 case value_t::discarded:
22300 default:
22301 {
22302 // all other types have size 1
22303 return 1;
22304 }
22305 }
22306 }
22307
22310 size_type max_size() const noexcept
22311 {
22312 switch (m_data.m_type)
22313 {
22314 case value_t::array:
22315 {
22316 // delegate call to array_t::max_size()
22317 return m_data.m_value.array->max_size();
22318 }
22319
22320 case value_t::object:
22321 {
22322 // delegate call to object_t::max_size()
22323 return m_data.m_value.object->max_size();
22324 }
22325
22326 case value_t::null:
22327 case value_t::string:
22328 case value_t::boolean:
22329 case value_t::number_integer:
22330 case value_t::number_unsigned:
22331 case value_t::number_float:
22332 case value_t::binary:
22333 case value_t::discarded:
22334 default:
22335 {
22336 // all other types have max_size() == size()
22337 return size();
22338 }
22339 }
22340 }
22341
22343
22345 // modifiers //
22347
22350
22353 void clear() noexcept
22354 {
22355 switch (m_data.m_type)
22356 {
22357 case value_t::number_integer:
22358 {
22359 m_data.m_value.number_integer = 0;
22360 break;
22361 }
22362
22363 case value_t::number_unsigned:
22364 {
22365 m_data.m_value.number_unsigned = 0;
22366 break;
22367 }
22368
22369 case value_t::number_float:
22370 {
22371 m_data.m_value.number_float = 0.0;
22372 break;
22373 }
22374
22375 case value_t::boolean:
22376 {
22377 m_data.m_value.boolean = false;
22378 break;
22379 }
22380
22381 case value_t::string:
22382 {
22383 m_data.m_value.string->clear();
22384 break;
22385 }
22386
22387 case value_t::binary:
22388 {
22389 m_data.m_value.binary->clear();
22390 break;
22391 }
22392
22393 case value_t::array:
22394 {
22395 m_data.m_value.array->clear();
22396 break;
22397 }
22398
22399 case value_t::object:
22400 {
22401 m_data.m_value.object->clear();
22402 break;
22403 }
22404
22405 case value_t::null:
22406 case value_t::discarded:
22407 default:
22408 break;
22409 }
22410 }
22411
22415 {
22416 // push_back only works for null objects or arrays
22417 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22418 {
22419 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22420 }
22421
22422 // transform null object into an array
22423 if (is_null())
22424 {
22425 m_data.m_type = value_t::array;
22426 m_data.m_value = value_t::array;
22427 assert_invariant();
22428 }
22429
22430 // add element to array (move semantics)
22431 const auto old_capacity = m_data.m_value.array->capacity();
22432 m_data.m_value.array->push_back(std::move(val));
22433 set_parent(m_data.m_value.array->back(), old_capacity);
22434 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22435 }
22436
22440 {
22441 push_back(std::move(val));
22442 return *this;
22443 }
22444
22447 void push_back(const basic_json& val)
22448 {
22449 // push_back only works for null objects or arrays
22450 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22451 {
22452 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22453 }
22454
22455 // transform null object into an array
22456 if (is_null())
22457 {
22458 m_data.m_type = value_t::array;
22459 m_data.m_value = value_t::array;
22460 assert_invariant();
22461 }
22462
22463 // add element to array
22464 const auto old_capacity = m_data.m_value.array->capacity();
22465 m_data.m_value.array->push_back(val);
22466 set_parent(m_data.m_value.array->back(), old_capacity);
22467 }
22468
22472 {
22473 push_back(val);
22474 return *this;
22475 }
22476
22479 void push_back(const typename object_t::value_type& val)
22480 {
22481 // push_back only works for null objects or objects
22482 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22483 {
22484 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22485 }
22486
22487 // transform null object into an object
22488 if (is_null())
22489 {
22490 m_data.m_type = value_t::object;
22491 m_data.m_value = value_t::object;
22492 assert_invariant();
22493 }
22494
22495 // add element to object
22496 auto res = m_data.m_value.object->insert(val);
22497 set_parent(res.first->second);
22498 }
22499
22502 reference operator+=(const typename object_t::value_type& val)
22503 {
22504 push_back(val);
22505 return *this;
22506 }
22507
22511 {
22512 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22513 {
22514 basic_json&& key = init.begin()->moved_or_copied();
22515 push_back(typename object_t::value_type(
22516 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22517 }
22518 else
22519 {
22520 push_back(basic_json(init));
22521 }
22522 }
22523
22527 {
22528 push_back(init);
22529 return *this;
22530 }
22531
22534 template<class... Args>
22535 reference emplace_back(Args&& ... args)
22536 {
22537 // emplace_back only works for null objects or arrays
22538 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22539 {
22540 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22541 }
22542
22543 // transform null object into an array
22544 if (is_null())
22545 {
22546 m_data.m_type = value_t::array;
22547 m_data.m_value = value_t::array;
22548 assert_invariant();
22549 }
22550
22551 // add element to array (perfect forwarding)
22552 const auto old_capacity = m_data.m_value.array->capacity();
22553 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22554 return set_parent(m_data.m_value.array->back(), old_capacity);
22555 }
22556
22559 template<class... Args>
22560 std::pair<iterator, bool> emplace(Args&& ... args)
22561 {
22562 // emplace only works for null objects or arrays
22563 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22564 {
22565 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22566 }
22567
22568 // transform null object into an object
22569 if (is_null())
22570 {
22571 m_data.m_type = value_t::object;
22572 m_data.m_value = value_t::object;
22573 assert_invariant();
22574 }
22575
22576 // add element to array (perfect forwarding)
22577 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22578 set_parent(res.first->second);
22579
22580 // create result iterator and set iterator to the result of emplace
22581 auto it = begin();
22582 it.m_it.object_iterator = res.first;
22583
22584 // return pair of iterator and boolean
22585 return {it, res.second};
22586 }
22587
22591 template<typename... Args>
22593 {
22594 iterator result(this);
22595 JSON_ASSERT(m_data.m_value.array != nullptr);
22596
22597 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22598 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22599 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22600
22601 // This could have been written as:
22602 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22603 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22604
22605 set_parents();
22606 return result;
22607 }
22608
22612 {
22613 // insert only works for arrays
22614 if (JSON_HEDLEY_LIKELY(is_array()))
22615 {
22616 // check if iterator pos fits to this JSON value
22617 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22618 {
22619 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22620 }
22621
22622 // insert to array and return iterator
22623 return insert_iterator(pos, val);
22624 }
22625
22626 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22627 }
22628
22632 {
22633 return insert(pos, val);
22634 }
22635
22639 {
22640 // insert only works for arrays
22641 if (JSON_HEDLEY_LIKELY(is_array()))
22642 {
22643 // check if iterator pos fits to this JSON value
22644 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22645 {
22646 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22647 }
22648
22649 // insert to array and return iterator
22650 return insert_iterator(pos, cnt, val);
22651 }
22652
22653 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22654 }
22655
22659 {
22660 // insert only works for arrays
22661 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22662 {
22663 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22664 }
22665
22666 // check if iterator pos fits to this JSON value
22667 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22668 {
22669 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22670 }
22671
22672 // check if range iterators belong to the same JSON object
22673 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22674 {
22675 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22676 }
22677
22678 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22679 {
22680 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22681 }
22682
22683 // insert to array and return iterator
22684 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22685 }
22686
22690 {
22691 // insert only works for arrays
22692 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22693 {
22694 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22695 }
22696
22697 // check if iterator pos fits to this JSON value
22698 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22699 {
22700 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22701 }
22702
22703 // insert to array and return iterator
22704 return insert_iterator(pos, ilist.begin(), ilist.end());
22705 }
22706
22710 {
22711 // insert only works for objects
22712 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22713 {
22714 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22715 }
22716
22717 // check if range iterators belong to the same JSON object
22718 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22719 {
22720 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22721 }
22722
22723 // passed iterators must belong to objects
22724 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22725 {
22726 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22727 }
22728
22729 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22730 }
22731
22734 void update(const_reference j, bool merge_objects = false)
22735 {
22736 update(j.begin(), j.end(), merge_objects);
22737 }
22738
22741 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22742 {
22743 // implicitly convert null value to an empty object
22744 if (is_null())
22745 {
22746 m_data.m_type = value_t::object;
22747 m_data.m_value.object = create<object_t>();
22748 assert_invariant();
22749 }
22750
22751 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22752 {
22753 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22754 }
22755
22756 // check if range iterators belong to the same JSON object
22757 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22758 {
22759 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22760 }
22761
22762 // passed iterators must belong to objects
22763 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22764 {
22765 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22766 }
22767
22768 for (auto it = first; it != last; ++it)
22769 {
22770 if (merge_objects && it.value().is_object())
22771 {
22772 auto it2 = m_data.m_value.object->find(it.key());
22773 if (it2 != m_data.m_value.object->end())
22774 {
22775 it2->second.update(it.value(), true);
22776 continue;
22777 }
22778 }
22779 m_data.m_value.object->operator[](it.key()) = it.value();
22780#if JSON_DIAGNOSTICS
22781 m_data.m_value.object->operator[](it.key()).m_parent = this;
22782#endif
22783 }
22784 }
22785
22788 void swap(reference other) noexcept (
22789 std::is_nothrow_move_constructible<value_t>::value&&
22790 std::is_nothrow_move_assignable<value_t>::value&&
22791 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22792 std::is_nothrow_move_assignable<json_value>::value
22793 )
22794 {
22795 std::swap(m_data.m_type, other.m_data.m_type);
22796 std::swap(m_data.m_value, other.m_data.m_value);
22797
22798 set_parents();
22799 other.set_parents();
22800 assert_invariant();
22801 }
22802
22805 friend void swap(reference left, reference right) noexcept (
22806 std::is_nothrow_move_constructible<value_t>::value&&
22807 std::is_nothrow_move_assignable<value_t>::value&&
22808 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22809 std::is_nothrow_move_assignable<json_value>::value
22810 )
22811 {
22812 left.swap(right);
22813 }
22814
22817 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22818 {
22819 // swap only works for arrays
22820 if (JSON_HEDLEY_LIKELY(is_array()))
22821 {
22822 using std::swap;
22823 swap(*(m_data.m_value.array), other);
22824 }
22825 else
22826 {
22827 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22828 }
22829 }
22830
22833 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22834 {
22835 // swap only works for objects
22836 if (JSON_HEDLEY_LIKELY(is_object()))
22837 {
22838 using std::swap;
22839 swap(*(m_data.m_value.object), other);
22840 }
22841 else
22842 {
22843 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22844 }
22845 }
22846
22849 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22850 {
22851 // swap only works for strings
22852 if (JSON_HEDLEY_LIKELY(is_string()))
22853 {
22854 using std::swap;
22855 swap(*(m_data.m_value.string), other);
22856 }
22857 else
22858 {
22859 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22860 }
22861 }
22862
22865 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22866 {
22867 // swap only works for strings
22868 if (JSON_HEDLEY_LIKELY(is_binary()))
22869 {
22870 using std::swap;
22871 swap(*(m_data.m_value.binary), other);
22872 }
22873 else
22874 {
22875 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22876 }
22877 }
22878
22881 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22882 {
22883 // swap only works for strings
22884 if (JSON_HEDLEY_LIKELY(is_binary()))
22885 {
22886 using std::swap;
22887 swap(*(m_data.m_value.binary), other);
22888 }
22889 else
22890 {
22891 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22892 }
22893 }
22894
22896
22898 // lexicographical comparison operators //
22900
22903
22904 // note parentheses around operands are necessary; see
22905 // https://github.com/nlohmann/json/issues/1530
22906#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22907 const auto lhs_type = lhs.type(); \
22908 const auto rhs_type = rhs.type(); \
22909 \
22910 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22911 { \
22912 switch (lhs_type) \
22913 { \
22914 case value_t::array: \
22915 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22916 \
22917 case value_t::object: \
22918 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22919 \
22920 case value_t::null: \
22921 return (null_result); \
22922 \
22923 case value_t::string: \
22924 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22925 \
22926 case value_t::boolean: \
22927 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22928 \
22929 case value_t::number_integer: \
22930 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22931 \
22932 case value_t::number_unsigned: \
22933 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22934 \
22935 case value_t::number_float: \
22936 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22937 \
22938 case value_t::binary: \
22939 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22940 \
22941 case value_t::discarded: \
22942 default: \
22943 return (unordered_result); \
22944 } \
22945 } \
22946 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22947 { \
22948 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22949 } \
22950 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22951 { \
22952 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22953 } \
22954 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22955 { \
22956 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22957 } \
22958 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22959 { \
22960 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22961 } \
22962 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22963 { \
22964 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22965 } \
22966 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22967 { \
22968 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22969 } \
22970 else if(compares_unordered(lhs, rhs))\
22971 {\
22972 return (unordered_result);\
22973 }\
22974 \
22975 return (default_result);
22976
22978 // returns true if:
22979 // - any operand is NaN and the other operand is of number type
22980 // - any operand is discarded
22981 // in legacy mode, discarded values are considered ordered if
22982 // an operation is computed as an odd number of inverses of others
22983 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22984 {
22985 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22986 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22987 {
22988 return true;
22989 }
22990#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22991 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22992#else
22993 static_cast<void>(inverse);
22994 return lhs.is_discarded() || rhs.is_discarded();
22995#endif
22996 }
22997
22998 private:
22999 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23000 {
23001 return compares_unordered(*this, rhs, inverse);
23002 }
23003
23004 public:
23005#if JSON_HAS_THREE_WAY_COMPARISON
23008 bool operator==(const_reference rhs) const noexcept
23009 {
23010#ifdef __GNUC__
23011#pragma GCC diagnostic push
23012#pragma GCC diagnostic ignored "-Wfloat-equal"
23013#endif
23014 const_reference lhs = *this;
23015 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23016#ifdef __GNUC__
23017#pragma GCC diagnostic pop
23018#endif
23019 }
23020
23023 template<typename ScalarType>
23024 requires std::is_scalar_v<ScalarType>
23025 bool operator==(ScalarType rhs) const noexcept
23026 {
23027 return *this == basic_json(rhs);
23028 }
23029
23032 bool operator!=(const_reference rhs) const noexcept
23033 {
23034 if (compares_unordered(rhs, true))
23035 {
23036 return false;
23037 }
23038 return !operator==(rhs);
23039 }
23040
23043 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23044 {
23045 const_reference lhs = *this;
23046 // default_result is used if we cannot compare values. In that case,
23047 // we compare types.
23048 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23049 std::partial_ordering::equivalent,
23050 std::partial_ordering::unordered,
23051 lhs_type <=> rhs_type) // *NOPAD*
23052 }
23053
23056 template<typename ScalarType>
23057 requires std::is_scalar_v<ScalarType>
23058 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23059 {
23060 return *this <=> basic_json(rhs); // *NOPAD*
23061 }
23062
23063#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23064 // all operators that are computed as an odd number of inverses of others
23065 // need to be overloaded to emulate the legacy comparison behavior
23066
23070 bool operator<=(const_reference rhs) const noexcept
23071 {
23072 if (compares_unordered(rhs, true))
23073 {
23074 return false;
23075 }
23076 return !(rhs < *this);
23077 }
23078
23081 template<typename ScalarType>
23082 requires std::is_scalar_v<ScalarType>
23083 bool operator<=(ScalarType rhs) const noexcept
23084 {
23085 return *this <= basic_json(rhs);
23086 }
23087
23091 bool operator>=(const_reference rhs) const noexcept
23092 {
23093 if (compares_unordered(rhs, true))
23094 {
23095 return false;
23096 }
23097 return !(*this < rhs);
23098 }
23099
23102 template<typename ScalarType>
23103 requires std::is_scalar_v<ScalarType>
23104 bool operator>=(ScalarType rhs) const noexcept
23105 {
23106 return *this >= basic_json(rhs);
23107 }
23108#endif
23109#else
23112 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23113 {
23114#ifdef __GNUC__
23115#pragma GCC diagnostic push
23116#pragma GCC diagnostic ignored "-Wfloat-equal"
23117#endif
23118 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23119#ifdef __GNUC__
23120#pragma GCC diagnostic pop
23121#endif
23122 }
23123
23126 template<typename ScalarType, typename std::enable_if<
23127 std::is_scalar<ScalarType>::value, int>::type = 0>
23128 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23129 {
23130 return lhs == basic_json(rhs);
23131 }
23132
23135 template<typename ScalarType, typename std::enable_if<
23136 std::is_scalar<ScalarType>::value, int>::type = 0>
23137 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23138 {
23139 return basic_json(lhs) == rhs;
23140 }
23141
23144 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23145 {
23146 if (compares_unordered(lhs, rhs, true))
23147 {
23148 return false;
23149 }
23150 return !(lhs == rhs);
23151 }
23152
23155 template<typename ScalarType, typename std::enable_if<
23156 std::is_scalar<ScalarType>::value, int>::type = 0>
23157 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23158 {
23159 return lhs != basic_json(rhs);
23160 }
23161
23164 template<typename ScalarType, typename std::enable_if<
23165 std::is_scalar<ScalarType>::value, int>::type = 0>
23166 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23167 {
23168 return basic_json(lhs) != rhs;
23169 }
23170
23173 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23174 {
23175 // default_result is used if we cannot compare values. In that case,
23176 // we compare types. Note we have to call the operator explicitly,
23177 // because MSVC has problems otherwise.
23178 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23179 }
23180
23183 template<typename ScalarType, typename std::enable_if<
23184 std::is_scalar<ScalarType>::value, int>::type = 0>
23185 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23186 {
23187 return lhs < basic_json(rhs);
23188 }
23189
23192 template<typename ScalarType, typename std::enable_if<
23193 std::is_scalar<ScalarType>::value, int>::type = 0>
23194 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23195 {
23196 return basic_json(lhs) < rhs;
23197 }
23198
23201 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23202 {
23203 if (compares_unordered(lhs, rhs, true))
23204 {
23205 return false;
23206 }
23207 return !(rhs < lhs);
23208 }
23209
23212 template<typename ScalarType, typename std::enable_if<
23213 std::is_scalar<ScalarType>::value, int>::type = 0>
23214 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23215 {
23216 return lhs <= basic_json(rhs);
23217 }
23218
23221 template<typename ScalarType, typename std::enable_if<
23222 std::is_scalar<ScalarType>::value, int>::type = 0>
23223 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23224 {
23225 return basic_json(lhs) <= rhs;
23226 }
23227
23230 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23231 {
23232 // double inverse
23233 if (compares_unordered(lhs, rhs))
23234 {
23235 return false;
23236 }
23237 return !(lhs <= rhs);
23238 }
23239
23242 template<typename ScalarType, typename std::enable_if<
23243 std::is_scalar<ScalarType>::value, int>::type = 0>
23244 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23245 {
23246 return lhs > basic_json(rhs);
23247 }
23248
23251 template<typename ScalarType, typename std::enable_if<
23252 std::is_scalar<ScalarType>::value, int>::type = 0>
23253 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23254 {
23255 return basic_json(lhs) > rhs;
23256 }
23257
23260 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23261 {
23262 if (compares_unordered(lhs, rhs, true))
23263 {
23264 return false;
23265 }
23266 return !(lhs < rhs);
23267 }
23268
23271 template<typename ScalarType, typename std::enable_if<
23272 std::is_scalar<ScalarType>::value, int>::type = 0>
23273 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23274 {
23275 return lhs >= basic_json(rhs);
23276 }
23277
23280 template<typename ScalarType, typename std::enable_if<
23281 std::is_scalar<ScalarType>::value, int>::type = 0>
23282 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23283 {
23284 return basic_json(lhs) >= rhs;
23285 }
23286#endif
23287
23288#undef JSON_IMPLEMENT_OPERATOR
23289
23291
23293 // serialization //
23295
23298#ifndef JSON_NO_IO
23301 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23302 {
23303 // read width member and use it as indentation parameter if nonzero
23304 const bool pretty_print = o.width() > 0;
23305 const auto indentation = pretty_print ? o.width() : 0;
23306
23307 // reset width to 0 for subsequent calls to this stream
23308 o.width(0);
23309
23310 // do the actual serialization
23311 serializer s(detail::output_adapter<char>(o), o.fill());
23312 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23313 return o;
23314 }
23315
23322 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23323 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23324 {
23325 return o << j;
23326 }
23327#endif // JSON_NO_IO
23329
23331 // deserialization //
23333
23336
23339 template<typename InputType>
23341 static basic_json parse(InputType&& i,
23342 const parser_callback_t cb = nullptr,
23343 const bool allow_exceptions = true,
23344 const bool ignore_comments = false)
23345 {
23346 basic_json result;
23347 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23348 return result;
23349 }
23350
23353 template<typename IteratorType>
23355 static basic_json parse(IteratorType first,
23356 IteratorType last,
23357 const parser_callback_t cb = nullptr,
23358 const bool allow_exceptions = true,
23359 const bool ignore_comments = false)
23360 {
23361 basic_json result;
23362 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23363 return result;
23364 }
23365
23367 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23368 static basic_json parse(detail::span_input_adapter&& i,
23369 const parser_callback_t cb = nullptr,
23370 const bool allow_exceptions = true,
23371 const bool ignore_comments = false)
23372 {
23373 basic_json result;
23374 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23375 return result;
23376 }
23377
23380 template<typename InputType>
23381 static bool accept(InputType&& i,
23382 const bool ignore_comments = false)
23383 {
23384 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23385 }
23386
23389 template<typename IteratorType>
23390 static bool accept(IteratorType first, IteratorType last,
23391 const bool ignore_comments = false)
23392 {
23393 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23394 }
23395
23397 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23398 static bool accept(detail::span_input_adapter&& i,
23399 const bool ignore_comments = false)
23400 {
23401 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23402 }
23403
23406 template <typename InputType, typename SAX>
23408 static bool sax_parse(InputType&& i, SAX* sax,
23410 const bool strict = true,
23411 const bool ignore_comments = false)
23412 {
23413 auto ia = detail::input_adapter(std::forward<InputType>(i));
23414 return format == input_format_t::json
23415 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23416 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23417 }
23418
23421 template<class IteratorType, class SAX>
23423 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23425 const bool strict = true,
23426 const bool ignore_comments = false)
23427 {
23428 auto ia = detail::input_adapter(std::move(first), std::move(last));
23429 return format == input_format_t::json
23430 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23431 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23432 }
23433
23439 template <typename SAX>
23440 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23442 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23444 const bool strict = true,
23445 const bool ignore_comments = false)
23446 {
23447 auto ia = i.get();
23448 return format == input_format_t::json
23449 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23450 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23451 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23452 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23453 }
23454#ifndef JSON_NO_IO
23461 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23462 friend std::istream& operator<<(basic_json& j, std::istream& i)
23463 {
23464 return operator>>(i, j);
23465 }
23466
23469 friend std::istream& operator>>(std::istream& i, basic_json& j)
23470 {
23471 parser(detail::input_adapter(i)).parse(false, j);
23472 return i;
23473 }
23474#endif // JSON_NO_IO
23476
23478 // convenience functions //
23480
23484 const char* type_name() const noexcept
23485 {
23486 switch (m_data.m_type)
23487 {
23488 case value_t::null:
23489 return "null";
23490 case value_t::object:
23491 return "object";
23492 case value_t::array:
23493 return "array";
23494 case value_t::string:
23495 return "string";
23496 case value_t::boolean:
23497 return "boolean";
23498 case value_t::binary:
23499 return "binary";
23500 case value_t::discarded:
23501 return "discarded";
23502 case value_t::number_integer:
23503 case value_t::number_unsigned:
23504 case value_t::number_float:
23505 default:
23506 return "number";
23507 }
23508 }
23509
23512 // member variables //
23514
23515 struct data
23516 {
23518 value_t m_type = value_t::null;
23519
23521 json_value m_value = {};
23522
23523 data(const value_t v)
23524 : m_type(v), m_value(v)
23525 {
23526 }
23527
23528 data(size_type cnt, const basic_json& val)
23529 : m_type(value_t::array)
23530 {
23531 m_value.array = create<array_t>(cnt, val);
23532 }
23533
23534 data() noexcept = default;
23535 data(data&&) noexcept = default;
23536 data(const data&) noexcept = delete;
23537 data& operator=(data&&) noexcept = delete;
23538 data& operator=(const data&) noexcept = delete;
23539
23540 ~data() noexcept
23541 {
23542 m_value.destroy(m_type);
23543 }
23544 };
23545
23546 data m_data = {};
23547
23548#if JSON_DIAGNOSTICS
23550 basic_json* m_parent = nullptr;
23551#endif
23552
23554 // binary serialization/deserialization //
23556
23559
23560 public:
23563 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23564 {
23565 std::vector<std::uint8_t> result;
23566 to_cbor(j, result);
23567 return result;
23568 }
23569
23573 {
23574 binary_writer<std::uint8_t>(o).write_cbor(j);
23575 }
23576
23580 {
23581 binary_writer<char>(o).write_cbor(j);
23582 }
23583
23586 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23587 {
23588 std::vector<std::uint8_t> result;
23589 to_msgpack(j, result);
23590 return result;
23591 }
23592
23596 {
23597 binary_writer<std::uint8_t>(o).write_msgpack(j);
23598 }
23599
23603 {
23604 binary_writer<char>(o).write_msgpack(j);
23605 }
23606
23609 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23610 const bool use_size = false,
23611 const bool use_type = false)
23612 {
23613 std::vector<std::uint8_t> result;
23614 to_ubjson(j, result, use_size, use_type);
23615 return result;
23616 }
23617
23621 const bool use_size = false, const bool use_type = false)
23622 {
23623 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23624 }
23625
23629 const bool use_size = false, const bool use_type = false)
23630 {
23631 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23632 }
23633
23636 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23637 const bool use_size = false,
23638 const bool use_type = false)
23639 {
23640 std::vector<std::uint8_t> result;
23641 to_bjdata(j, result, use_size, use_type);
23642 return result;
23643 }
23644
23648 const bool use_size = false, const bool use_type = false)
23649 {
23650 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23651 }
23652
23656 const bool use_size = false, const bool use_type = false)
23657 {
23658 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23659 }
23660
23663 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23664 {
23665 std::vector<std::uint8_t> result;
23666 to_bson(j, result);
23667 return result;
23668 }
23669
23673 {
23674 binary_writer<std::uint8_t>(o).write_bson(j);
23675 }
23676
23680 {
23681 binary_writer<char>(o).write_bson(j);
23682 }
23683
23686 template<typename InputType>
23688 static basic_json from_cbor(InputType&& i,
23689 const bool strict = true,
23690 const bool allow_exceptions = true,
23691 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23692 {
23693 basic_json result;
23694 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23695 auto ia = detail::input_adapter(std::forward<InputType>(i));
23696 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23697 return res ? result : basic_json(value_t::discarded);
23698 }
23699
23702 template<typename IteratorType>
23704 static basic_json from_cbor(IteratorType first, IteratorType last,
23705 const bool strict = true,
23706 const bool allow_exceptions = true,
23707 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23708 {
23709 basic_json result;
23710 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23711 auto ia = detail::input_adapter(std::move(first), std::move(last));
23712 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23713 return res ? result : basic_json(value_t::discarded);
23714 }
23715
23716 template<typename T>
23718 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23719 static basic_json from_cbor(const T* ptr, std::size_t len,
23720 const bool strict = true,
23721 const bool allow_exceptions = true,
23722 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23723 {
23724 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23725 }
23726
23728 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23729 static basic_json from_cbor(detail::span_input_adapter&& i,
23730 const bool strict = true,
23731 const bool allow_exceptions = true,
23732 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23733 {
23734 basic_json result;
23735 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23736 auto ia = i.get();
23737 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23738 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23739 return res ? result : basic_json(value_t::discarded);
23740 }
23741
23744 template<typename InputType>
23746 static basic_json from_msgpack(InputType&& i,
23747 const bool strict = true,
23748 const bool allow_exceptions = true)
23749 {
23750 basic_json result;
23751 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23752 auto ia = detail::input_adapter(std::forward<InputType>(i));
23753 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23754 return res ? result : basic_json(value_t::discarded);
23755 }
23756
23759 template<typename IteratorType>
23761 static basic_json from_msgpack(IteratorType first, IteratorType last,
23762 const bool strict = true,
23763 const bool allow_exceptions = true)
23764 {
23765 basic_json result;
23766 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23767 auto ia = detail::input_adapter(std::move(first), std::move(last));
23768 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23769 return res ? result : basic_json(value_t::discarded);
23770 }
23771
23772 template<typename T>
23774 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23775 static basic_json from_msgpack(const T* ptr, std::size_t len,
23776 const bool strict = true,
23777 const bool allow_exceptions = true)
23778 {
23779 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23780 }
23781
23783 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23784 static basic_json from_msgpack(detail::span_input_adapter&& i,
23785 const bool strict = true,
23786 const bool allow_exceptions = true)
23787 {
23788 basic_json result;
23789 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23790 auto ia = i.get();
23791 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23792 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23793 return res ? result : basic_json(value_t::discarded);
23794 }
23795
23798 template<typename InputType>
23800 static basic_json from_ubjson(InputType&& i,
23801 const bool strict = true,
23802 const bool allow_exceptions = true)
23803 {
23804 basic_json result;
23805 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23806 auto ia = detail::input_adapter(std::forward<InputType>(i));
23807 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23808 return res ? result : basic_json(value_t::discarded);
23809 }
23810
23813 template<typename IteratorType>
23815 static basic_json from_ubjson(IteratorType first, IteratorType last,
23816 const bool strict = true,
23817 const bool allow_exceptions = true)
23818 {
23819 basic_json result;
23820 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23821 auto ia = detail::input_adapter(std::move(first), std::move(last));
23822 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23823 return res ? result : basic_json(value_t::discarded);
23824 }
23825
23826 template<typename T>
23828 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23829 static basic_json from_ubjson(const T* ptr, std::size_t len,
23830 const bool strict = true,
23831 const bool allow_exceptions = true)
23832 {
23833 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23834 }
23835
23837 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23838 static basic_json from_ubjson(detail::span_input_adapter&& i,
23839 const bool strict = true,
23840 const bool allow_exceptions = true)
23841 {
23842 basic_json result;
23843 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23844 auto ia = i.get();
23845 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23846 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23847 return res ? result : basic_json(value_t::discarded);
23848 }
23849
23852 template<typename InputType>
23854 static basic_json from_bjdata(InputType&& i,
23855 const bool strict = true,
23856 const bool allow_exceptions = true)
23857 {
23858 basic_json result;
23859 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23860 auto ia = detail::input_adapter(std::forward<InputType>(i));
23861 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23862 return res ? result : basic_json(value_t::discarded);
23863 }
23864
23867 template<typename IteratorType>
23869 static basic_json from_bjdata(IteratorType first, IteratorType last,
23870 const bool strict = true,
23871 const bool allow_exceptions = true)
23872 {
23873 basic_json result;
23874 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23875 auto ia = detail::input_adapter(std::move(first), std::move(last));
23876 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23877 return res ? result : basic_json(value_t::discarded);
23878 }
23879
23882 template<typename InputType>
23884 static basic_json from_bson(InputType&& i,
23885 const bool strict = true,
23886 const bool allow_exceptions = true)
23887 {
23888 basic_json result;
23889 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23890 auto ia = detail::input_adapter(std::forward<InputType>(i));
23891 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23892 return res ? result : basic_json(value_t::discarded);
23893 }
23894
23897 template<typename IteratorType>
23899 static basic_json from_bson(IteratorType first, IteratorType last,
23900 const bool strict = true,
23901 const bool allow_exceptions = true)
23902 {
23903 basic_json result;
23904 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23905 auto ia = detail::input_adapter(std::move(first), std::move(last));
23906 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23907 return res ? result : basic_json(value_t::discarded);
23908 }
23909
23910 template<typename T>
23912 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23913 static basic_json from_bson(const T* ptr, std::size_t len,
23914 const bool strict = true,
23915 const bool allow_exceptions = true)
23916 {
23917 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23918 }
23919
23921 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23922 static basic_json from_bson(detail::span_input_adapter&& i,
23923 const bool strict = true,
23924 const bool allow_exceptions = true)
23925 {
23926 basic_json result;
23927 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23928 auto ia = i.get();
23929 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23930 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23931 return res ? result : basic_json(value_t::discarded);
23932 }
23934
23936 // JSON Pointer support //
23938
23941
23945 {
23946 return ptr.get_unchecked(this);
23947 }
23948
23949 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23950 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23951 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23952 {
23953 return ptr.get_unchecked(this);
23954 }
23955
23959 {
23960 return ptr.get_unchecked(this);
23961 }
23962
23963 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23964 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23965 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23966 {
23967 return ptr.get_unchecked(this);
23968 }
23969
23973 {
23974 return ptr.get_checked(this);
23975 }
23976
23977 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23978 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23979 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23980 {
23981 return ptr.get_checked(this);
23982 }
23983
23987 {
23988 return ptr.get_checked(this);
23989 }
23990
23991 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23992 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23993 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23994 {
23995 return ptr.get_checked(this);
23996 }
23997
24001 {
24002 basic_json result(value_t::object);
24003 json_pointer::flatten("", *this, result);
24004 return result;
24005 }
24006
24010 {
24011 return json_pointer::unflatten(*this);
24012 }
24013
24015
24017 // JSON Patch functions //
24019
24022
24025 void patch_inplace(const basic_json& json_patch)
24026 {
24027 basic_json& result = *this;
24028 // the valid JSON Patch operations
24029 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24030
24031 const auto get_op = [](const std::string & op)
24032 {
24033 if (op == "add")
24034 {
24035 return patch_operations::add;
24036 }
24037 if (op == "remove")
24038 {
24039 return patch_operations::remove;
24040 }
24041 if (op == "replace")
24042 {
24043 return patch_operations::replace;
24044 }
24045 if (op == "move")
24046 {
24047 return patch_operations::move;
24048 }
24049 if (op == "copy")
24050 {
24051 return patch_operations::copy;
24052 }
24053 if (op == "test")
24054 {
24055 return patch_operations::test;
24056 }
24057
24058 return patch_operations::invalid;
24059 };
24060
24061 // wrapper for "add" operation; add value at ptr
24062 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24063 {
24064 // adding to the root of the target document means replacing it
24065 if (ptr.empty())
24066 {
24067 result = val;
24068 return;
24069 }
24070
24071 // make sure the top element of the pointer exists
24072 json_pointer const top_pointer = ptr.top();
24073 if (top_pointer != ptr)
24074 {
24075 result.at(top_pointer);
24076 }
24077
24078 // get reference to parent of JSON pointer ptr
24079 const auto last_path = ptr.back();
24080 ptr.pop_back();
24081 // parent must exist when performing patch add per RFC6902 specs
24082 basic_json& parent = result.at(ptr);
24083
24084 switch (parent.m_data.m_type)
24085 {
24086 case value_t::null:
24087 case value_t::object:
24088 {
24089 // use operator[] to add value
24090 parent[last_path] = val;
24091 break;
24092 }
24093
24094 case value_t::array:
24095 {
24096 if (last_path == "-")
24097 {
24098 // special case: append to back
24099 parent.push_back(val);
24100 }
24101 else
24102 {
24103 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24104 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24105 {
24106 // avoid undefined behavior
24107 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24108 }
24109
24110 // default case: insert add offset
24111 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24112 }
24113 break;
24114 }
24115
24116 // if there exists a parent it cannot be primitive
24117 case value_t::string: // LCOV_EXCL_LINE
24118 case value_t::boolean: // LCOV_EXCL_LINE
24119 case value_t::number_integer: // LCOV_EXCL_LINE
24120 case value_t::number_unsigned: // LCOV_EXCL_LINE
24121 case value_t::number_float: // LCOV_EXCL_LINE
24122 case value_t::binary: // LCOV_EXCL_LINE
24123 case value_t::discarded: // LCOV_EXCL_LINE
24124 default: // LCOV_EXCL_LINE
24125 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24126 }
24127 };
24128
24129 // wrapper for "remove" operation; remove value at ptr
24130 const auto operation_remove = [this, & result](json_pointer & ptr)
24131 {
24132 // get reference to parent of JSON pointer ptr
24133 const auto last_path = ptr.back();
24134 ptr.pop_back();
24135 basic_json& parent = result.at(ptr);
24136
24137 // remove child
24138 if (parent.is_object())
24139 {
24140 // perform range check
24141 auto it = parent.find(last_path);
24142 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24143 {
24144 parent.erase(it);
24145 }
24146 else
24147 {
24148 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24149 }
24150 }
24151 else if (parent.is_array())
24152 {
24153 // note erase performs range check
24154 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24155 }
24156 };
24157
24158 // type check: top level value must be an array
24159 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24160 {
24161 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24162 }
24163
24164 // iterate and apply the operations
24165 for (const auto& val : json_patch)
24166 {
24167 // wrapper to get a value for an operation
24168 const auto get_value = [&val](const std::string & op,
24169 const std::string & member,
24170 bool string_type) -> basic_json &
24171 {
24172 // find value
24173 auto it = val.m_data.m_value.object->find(member);
24174
24175 // context-sensitive error message
24176 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24177
24178 // check if desired value is present
24179 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24180 {
24181 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24182 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24183 }
24184
24185 // check if result is of type string
24186 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24187 {
24188 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24189 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24190 }
24191
24192 // no error: return value
24193 return it->second;
24194 };
24195
24196 // type check: every element of the array must be an object
24197 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24198 {
24199 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24200 }
24201
24202 // collect mandatory members
24203 const auto op = get_value("op", "op", true).template get<std::string>();
24204 const auto path = get_value(op, "path", true).template get<std::string>();
24205 json_pointer ptr(path);
24206
24207 switch (get_op(op))
24208 {
24209 case patch_operations::add:
24210 {
24211 operation_add(ptr, get_value("add", "value", false));
24212 break;
24213 }
24214
24215 case patch_operations::remove:
24216 {
24217 operation_remove(ptr);
24218 break;
24219 }
24220
24221 case patch_operations::replace:
24222 {
24223 // the "path" location must exist - use at()
24224 result.at(ptr) = get_value("replace", "value", false);
24225 break;
24226 }
24227
24228 case patch_operations::move:
24229 {
24230 const auto from_path = get_value("move", "from", true).template get<std::string>();
24231 json_pointer from_ptr(from_path);
24232
24233 // the "from" location must exist - use at()
24234 basic_json const v = result.at(from_ptr);
24235
24236 // The move operation is functionally identical to a
24237 // "remove" operation on the "from" location, followed
24238 // immediately by an "add" operation at the target
24239 // location with the value that was just removed.
24240 operation_remove(from_ptr);
24241 operation_add(ptr, v);
24242 break;
24243 }
24244
24245 case patch_operations::copy:
24246 {
24247 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24248 const json_pointer from_ptr(from_path);
24249
24250 // the "from" location must exist - use at()
24251 basic_json const v = result.at(from_ptr);
24252
24253 // The copy is functionally identical to an "add"
24254 // operation at the target location using the value
24255 // specified in the "from" member.
24256 operation_add(ptr, v);
24257 break;
24258 }
24259
24260 case patch_operations::test:
24261 {
24262 bool success = false;
24263 JSON_TRY
24264 {
24265 // check if "value" matches the one at "path"
24266 // the "path" location must exist - use at()
24267 success = (result.at(ptr) == get_value("test", "value", false));
24268 }
24270 {
24271 // ignore out of range errors: success remains false
24272 }
24273
24274 // throw an exception if test fails
24275 if (JSON_HEDLEY_UNLIKELY(!success))
24276 {
24277 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24278 }
24279
24280 break;
24281 }
24282
24283 case patch_operations::invalid:
24284 default:
24285 {
24286 // op must be "add", "remove", "replace", "move", "copy", or
24287 // "test"
24288 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24289 }
24290 }
24291 }
24292 }
24293
24296 basic_json patch(const basic_json& json_patch) const
24297 {
24298 basic_json result = *this;
24299 result.patch_inplace(json_patch);
24300 return result;
24301 }
24302
24306 static basic_json diff(const basic_json& source, const basic_json& target,
24307 const std::string& path = "")
24308 {
24309 // the patch
24310 basic_json result(value_t::array);
24311
24312 // if the values are the same, return empty patch
24313 if (source == target)
24314 {
24315 return result;
24316 }
24317
24318 if (source.type() != target.type())
24319 {
24320 // different types: replace value
24321 result.push_back(
24322 {
24323 {"op", "replace"}, {"path", path}, {"value", target}
24324 });
24325 return result;
24326 }
24327
24328 switch (source.type())
24329 {
24330 case value_t::array:
24331 {
24332 // first pass: traverse common elements
24333 std::size_t i = 0;
24334 while (i < source.size() && i < target.size())
24335 {
24336 // recursive call to compare array values at index i
24337 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24338 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24339 ++i;
24340 }
24341
24342 // We now reached the end of at least one array
24343 // in a second pass, traverse the remaining elements
24344
24345 // remove my remaining elements
24346 const auto end_index = static_cast<difference_type>(result.size());
24347 while (i < source.size())
24348 {
24349 // add operations in reverse order to avoid invalid
24350 // indices
24351 result.insert(result.begin() + end_index, object(
24352 {
24353 {"op", "remove"},
24354 {"path", detail::concat(path, '/', std::to_string(i))}
24355 }));
24356 ++i;
24357 }
24358
24359 // add other remaining elements
24360 while (i < target.size())
24361 {
24362 result.push_back(
24363 {
24364 {"op", "add"},
24365 {"path", detail::concat(path, "/-")},
24366 {"value", target[i]}
24367 });
24368 ++i;
24369 }
24370
24371 break;
24372 }
24373
24374 case value_t::object:
24375 {
24376 // first pass: traverse this object's elements
24377 for (auto it = source.cbegin(); it != source.cend(); ++it)
24378 {
24379 // escape the key name to be used in a JSON patch
24380 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24381
24382 if (target.find(it.key()) != target.end())
24383 {
24384 // recursive call to compare object values at key it
24385 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24386 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24387 }
24388 else
24389 {
24390 // found a key that is not in o -> remove it
24391 result.push_back(object(
24392 {
24393 {"op", "remove"}, {"path", path_key}
24394 }));
24395 }
24396 }
24397
24398 // second pass: traverse other object's elements
24399 for (auto it = target.cbegin(); it != target.cend(); ++it)
24400 {
24401 if (source.find(it.key()) == source.end())
24402 {
24403 // found a key that is not in this -> add it
24404 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24405 result.push_back(
24406 {
24407 {"op", "add"}, {"path", path_key},
24408 {"value", it.value()}
24409 });
24410 }
24411 }
24412
24413 break;
24414 }
24415
24416 case value_t::null:
24417 case value_t::string:
24418 case value_t::boolean:
24419 case value_t::number_integer:
24420 case value_t::number_unsigned:
24421 case value_t::number_float:
24422 case value_t::binary:
24423 case value_t::discarded:
24424 default:
24425 {
24426 // both primitive type: replace value
24427 result.push_back(
24428 {
24429 {"op", "replace"}, {"path", path}, {"value", target}
24430 });
24431 break;
24432 }
24433 }
24434
24435 return result;
24436 }
24438
24440 // JSON Merge Patch functions //
24442
24445
24448 void merge_patch(const basic_json& apply_patch)
24449 {
24450 if (apply_patch.is_object())
24451 {
24452 if (!is_object())
24453 {
24454 *this = object();
24455 }
24456 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24457 {
24458 if (it.value().is_null())
24459 {
24460 erase(it.key());
24461 }
24462 else
24463 {
24464 operator[](it.key()).merge_patch(it.value());
24465 }
24466 }
24467 }
24468 else
24469 {
24470 *this = apply_patch;
24471 }
24472 }
24473
24475};
24476
24481{
24482 return j.dump();
24483}
24484
24485inline namespace literals
24486{
24487inline namespace json_literals
24488{
24489
24493#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24494 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24495#else
24496 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24497#endif
24498{
24499 return nlohmann::json::parse(s, s + n);
24500}
24501
24505#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24506 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24507#else
24508 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24509#endif
24510{
24511 return nlohmann::json::json_pointer(std::string(s, n));
24512}
24513
24514} // namespace json_literals
24515} // namespace literals
24517
24519// nonmember support //
24521
24522namespace std // NOLINT(cert-dcl58-cpp)
24523{
24524
24528struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24529{
24530 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24531 {
24532 return nlohmann::detail::hash(j);
24533 }
24534};
24535
24536// specialization for std::less<value_t>
24537template<>
24538struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24539{
24544 bool operator()(::nlohmann::detail::value_t lhs,
24545 ::nlohmann::detail::value_t rhs) const noexcept
24546 {
24547#if JSON_HAS_THREE_WAY_COMPARISON
24548 return std::is_lt(lhs <=> rhs); // *NOPAD*
24549#else
24550 return ::nlohmann::detail::operator<(lhs, rhs);
24551#endif
24552 }
24553};
24554
24555// C++20 prohibit function specialization in the std namespace.
24556#ifndef JSON_HAS_CPP_20
24557
24561inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24562 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24563 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24564{
24565 j1.swap(j2);
24566}
24567
24568#endif
24569
24570} // namespace std
24571
24572#if JSON_USE_GLOBAL_UDLS
24573 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24574 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24575 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24576 #else
24577 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24578 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24579 #endif
24580#endif
24581
24582// #include <nlohmann/detail/macro_unscope.hpp>
24583// __ _____ _____ _____
24584// __| | __| | | | JSON for Modern C++
24585// | | |__ | | | | | | version 3.11.3
24586// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24587//
24588// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24589// SPDX-License-Identifier: MIT
24590
24591
24592
24593// restore clang diagnostic settings
24594#if defined(__clang__)
24595 #pragma clang diagnostic pop
24596#endif
24597
24598// clean up
24599#undef JSON_ASSERT
24600#undef JSON_INTERNAL_CATCH
24601#undef JSON_THROW
24602#undef JSON_PRIVATE_UNLESS_TESTED
24603#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24604#undef NLOHMANN_BASIC_JSON_TPL
24605#undef JSON_EXPLICIT
24606#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24607#undef JSON_INLINE_VARIABLE
24608#undef JSON_NO_UNIQUE_ADDRESS
24609#undef JSON_DISABLE_ENUM_SERIALIZATION
24610#undef JSON_USE_GLOBAL_UDLS
24611
24612#ifndef JSON_TEST_KEEP_MACROS
24613 #undef JSON_CATCH
24614 #undef JSON_TRY
24615 #undef JSON_HAS_CPP_11
24616 #undef JSON_HAS_CPP_14
24617 #undef JSON_HAS_CPP_17
24618 #undef JSON_HAS_CPP_20
24619 #undef JSON_HAS_FILESYSTEM
24620 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24621 #undef JSON_HAS_THREE_WAY_COMPARISON
24622 #undef JSON_HAS_RANGES
24623 #undef JSON_HAS_STATIC_RTTI
24624 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24625#endif
24626
24627// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24628// __ _____ _____ _____
24629// __| | __| | | | JSON for Modern C++
24630// | | |__ | | | | | | version 3.11.3
24631// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24632//
24633// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24634// SPDX-License-Identifier: MIT
24635
24636
24637
24638#undef JSON_HEDLEY_ALWAYS_INLINE
24639#undef JSON_HEDLEY_ARM_VERSION
24640#undef JSON_HEDLEY_ARM_VERSION_CHECK
24641#undef JSON_HEDLEY_ARRAY_PARAM
24642#undef JSON_HEDLEY_ASSUME
24643#undef JSON_HEDLEY_BEGIN_C_DECLS
24644#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24645#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24646#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24647#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24648#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24649#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24650#undef JSON_HEDLEY_CLANG_HAS_WARNING
24651#undef JSON_HEDLEY_COMPCERT_VERSION
24652#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24653#undef JSON_HEDLEY_CONCAT
24654#undef JSON_HEDLEY_CONCAT3
24655#undef JSON_HEDLEY_CONCAT3_EX
24656#undef JSON_HEDLEY_CONCAT_EX
24657#undef JSON_HEDLEY_CONST
24658#undef JSON_HEDLEY_CONSTEXPR
24659#undef JSON_HEDLEY_CONST_CAST
24660#undef JSON_HEDLEY_CPP_CAST
24661#undef JSON_HEDLEY_CRAY_VERSION
24662#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24663#undef JSON_HEDLEY_C_DECL
24664#undef JSON_HEDLEY_DEPRECATED
24665#undef JSON_HEDLEY_DEPRECATED_FOR
24666#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24667#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24668#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24669#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24670#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24671#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24672#undef JSON_HEDLEY_DIAGNOSTIC_POP
24673#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24674#undef JSON_HEDLEY_DMC_VERSION
24675#undef JSON_HEDLEY_DMC_VERSION_CHECK
24676#undef JSON_HEDLEY_EMPTY_BASES
24677#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24678#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24679#undef JSON_HEDLEY_END_C_DECLS
24680#undef JSON_HEDLEY_FLAGS
24681#undef JSON_HEDLEY_FLAGS_CAST
24682#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24683#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24684#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24685#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24686#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24687#undef JSON_HEDLEY_GCC_HAS_FEATURE
24688#undef JSON_HEDLEY_GCC_HAS_WARNING
24689#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24690#undef JSON_HEDLEY_GCC_VERSION
24691#undef JSON_HEDLEY_GCC_VERSION_CHECK
24692#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24693#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24694#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24695#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24696#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24697#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24698#undef JSON_HEDLEY_GNUC_HAS_WARNING
24699#undef JSON_HEDLEY_GNUC_VERSION
24700#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24701#undef JSON_HEDLEY_HAS_ATTRIBUTE
24702#undef JSON_HEDLEY_HAS_BUILTIN
24703#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24704#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24705#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24706#undef JSON_HEDLEY_HAS_EXTENSION
24707#undef JSON_HEDLEY_HAS_FEATURE
24708#undef JSON_HEDLEY_HAS_WARNING
24709#undef JSON_HEDLEY_IAR_VERSION
24710#undef JSON_HEDLEY_IAR_VERSION_CHECK
24711#undef JSON_HEDLEY_IBM_VERSION
24712#undef JSON_HEDLEY_IBM_VERSION_CHECK
24713#undef JSON_HEDLEY_IMPORT
24714#undef JSON_HEDLEY_INLINE
24715#undef JSON_HEDLEY_INTEL_CL_VERSION
24716#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24717#undef JSON_HEDLEY_INTEL_VERSION
24718#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24719#undef JSON_HEDLEY_IS_CONSTANT
24720#undef JSON_HEDLEY_IS_CONSTEXPR_
24721#undef JSON_HEDLEY_LIKELY
24722#undef JSON_HEDLEY_MALLOC
24723#undef JSON_HEDLEY_MCST_LCC_VERSION
24724#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24725#undef JSON_HEDLEY_MESSAGE
24726#undef JSON_HEDLEY_MSVC_VERSION
24727#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24728#undef JSON_HEDLEY_NEVER_INLINE
24729#undef JSON_HEDLEY_NON_NULL
24730#undef JSON_HEDLEY_NO_ESCAPE
24731#undef JSON_HEDLEY_NO_RETURN
24732#undef JSON_HEDLEY_NO_THROW
24733#undef JSON_HEDLEY_NULL
24734#undef JSON_HEDLEY_PELLES_VERSION
24735#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24736#undef JSON_HEDLEY_PGI_VERSION
24737#undef JSON_HEDLEY_PGI_VERSION_CHECK
24738#undef JSON_HEDLEY_PREDICT
24739#undef JSON_HEDLEY_PRINTF_FORMAT
24740#undef JSON_HEDLEY_PRIVATE
24741#undef JSON_HEDLEY_PUBLIC
24742#undef JSON_HEDLEY_PURE
24743#undef JSON_HEDLEY_REINTERPRET_CAST
24744#undef JSON_HEDLEY_REQUIRE
24745#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24746#undef JSON_HEDLEY_REQUIRE_MSG
24747#undef JSON_HEDLEY_RESTRICT
24748#undef JSON_HEDLEY_RETURNS_NON_NULL
24749#undef JSON_HEDLEY_SENTINEL
24750#undef JSON_HEDLEY_STATIC_ASSERT
24751#undef JSON_HEDLEY_STATIC_CAST
24752#undef JSON_HEDLEY_STRINGIFY
24753#undef JSON_HEDLEY_STRINGIFY_EX
24754#undef JSON_HEDLEY_SUNPRO_VERSION
24755#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24756#undef JSON_HEDLEY_TINYC_VERSION
24757#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24758#undef JSON_HEDLEY_TI_ARMCL_VERSION
24759#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24760#undef JSON_HEDLEY_TI_CL2000_VERSION
24761#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24762#undef JSON_HEDLEY_TI_CL430_VERSION
24763#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24764#undef JSON_HEDLEY_TI_CL6X_VERSION
24765#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24766#undef JSON_HEDLEY_TI_CL7X_VERSION
24767#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24768#undef JSON_HEDLEY_TI_CLPRU_VERSION
24769#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24770#undef JSON_HEDLEY_TI_VERSION
24771#undef JSON_HEDLEY_TI_VERSION_CHECK
24772#undef JSON_HEDLEY_UNAVAILABLE
24773#undef JSON_HEDLEY_UNLIKELY
24774#undef JSON_HEDLEY_UNPREDICTABLE
24775#undef JSON_HEDLEY_UNREACHABLE
24776#undef JSON_HEDLEY_UNREACHABLE_RETURN
24777#undef JSON_HEDLEY_VERSION
24778#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24779#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24780#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24781#undef JSON_HEDLEY_VERSION_ENCODE
24782#undef JSON_HEDLEY_WARNING
24783#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24784#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24785#undef JSON_HEDLEY_FALL_THROUGH
24786
24787
24788
24789#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
定义 json.hpp:19425
constexpr bool is_string() const noexcept
return whether value is a string
定义 json.hpp:20697
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
定义 json.hpp:21930
reference operator[](KeyType &&key)
access specified object element
定义 json.hpp:21498
size_type size() const noexcept
returns the number of elements
定义 json.hpp:22271
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
定义 json.hpp:23704
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
定义 json.hpp:23636
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
定义 json.hpp:21070
const_iterator end() const noexcept
returns an iterator to one past the last element
定义 json.hpp:22128
reference back()
access the last element
定义 json.hpp:21734
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
定义 json.hpp:20161
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
定义 json.hpp:22144
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
定义 json.hpp:24296
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
定义 json.hpp:23484
const_reference front() const
access the first element
定义 json.hpp:21727
constexpr bool is_array() const noexcept
return whether value is an array
定义 json.hpp:20690
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
定义 json.hpp:22788
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:21678
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
定义 json.hpp:22047
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
定义 json.hpp:19556
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
定义 json.hpp:23655
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
定义 json.hpp:20662
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
定义 json.hpp:19560
data(size_type cnt, const basic_json &val)
定义 json.hpp:23528
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
定义 json.hpp:23899
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
定义 json.hpp:23647
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
定义 json.hpp:23944
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
定义 json.hpp:19551
std::size_t size_type
a type to represent container sizes
定义 json.hpp:19543
constexpr bool is_structured() const noexcept
return whether type is structured
定义 json.hpp:20634
const_reference operator[](KeyType &&key) const
access specified object element
定义 json.hpp:21522
void swap(binary_t &other)
exchanges the values
定义 json.hpp:22865
ReferenceType get_ref()
get a reference value (implicit)
定义 json.hpp:21160
size_type max_size() const noexcept
returns the maximum possible number of elements
定义 json.hpp:22310
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
定义 json.hpp:22734
ReferenceType get_ref() const
get a reference value (implicit)
定义 json.hpp:21171
constexpr bool is_discarded() const noexcept
return whether value is discarded
定义 json.hpp:20711
reference operator+=(initializer_list_t init)
add an object to an object
定义 json.hpp:22526
void push_back(basic_json &&val)
add an object to an array
定义 json.hpp:22414
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
定义 json.hpp:21467
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
定义 json.hpp:22216
const_reference back() const
access the last element
定义 json.hpp:21743
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
定义 json.hpp:21825
reference operator+=(const basic_json &val)
add an object to an array
定义 json.hpp:22471
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
定义 json.hpp:22805
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
定义 json.hpp:23800
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
定义 json.hpp:20298
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
定义 json.hpp:22638
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
定义 json.hpp:23884
static allocator_type get_allocator()
returns the allocator associated with the container
定义 json.hpp:19566
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
定义 json.hpp:19691
reference at(KeyType &&key)
access specified object element with bounds checking
定义 json.hpp:21330
iterator end() noexcept
returns an iterator to one past the last element
定义 json.hpp:22119
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
定义 json.hpp:20669
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
定义 json.hpp:22741
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
定义 json.hpp:23663
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
定义 json.hpp:22151
data m_data
定义 json.hpp:23546
void push_back(initializer_list_t init)
add an object to an object
定义 json.hpp:22510
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
定义 json.hpp:20128
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
定义 json.hpp:20339
ValueType & get_to(ValueType &v) const
定义 json.hpp:21137
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
定义 json.hpp:23602
iterator begin() noexcept
returns an iterator to the first element
定义 json.hpp:22094
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
定义 json.hpp:21577
const_iterator cend() const noexcept
returns an iterator to one past the last element
定义 json.hpp:22135
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
定义 json.hpp:23854
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
定义 json.hpp:23986
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
定义 json.hpp:20309
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
定义 json.hpp:20149
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
定义 json.hpp:23688
basic_json flatten() const
return flattened JSON value
定义 json.hpp:24000
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
定义 json.hpp:23815
size_type erase(KeyType &&key)
remove element from a JSON object given a key
定义 json.hpp:21941
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
定义 json.hpp:19667
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
定义 json.hpp:19659
const binary_t & get_binary() const
get a binary value
定义 json.hpp:21242
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
定义 json.hpp:22658
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
定义 json.hpp:24025
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:21630
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
定义 json.hpp:24306
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
定义 json.hpp:23958
value_type & reference
the type of an element reference
定义 json.hpp:19536
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
定义 json.hpp:19500
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
定义 json.hpp:22064
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
定义 json.hpp:23572
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
定义 json.hpp:23679
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
定义 json.hpp:21977
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
定义 json.hpp:20287
const_reference at(KeyType &&key) const
access specified object element with bounds checking
定义 json.hpp:21368
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
定义 json.hpp:19574
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
定义 json.hpp:20346
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
定义 json.hpp:21991
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
定义 json.hpp:23563
IteratorType erase(IteratorType pos)
remove element given an iterator
定义 json.hpp:21755
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
定义 json.hpp:22611
NumberFloatType number_float_t
a type for a number (floating-point)
定义 json.hpp:19687
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
定义 json.hpp:21552
AllocatorType< basic_json > allocator_type
the allocator type
定义 json.hpp:19546
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
定义 json.hpp:19549
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
定义 json.hpp:20598
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
定义 json.hpp:24448
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
定义 json.hpp:21124
reference operator[](T *key)
定义 json.hpp:21483
reference at(size_type idx)
access specified array element with bounds checking
定义 json.hpp:21264
iterator find(KeyType &&key)
find an element in a JSON object
定义 json.hpp:22007
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
定义 json.hpp:20676
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
定义 json.hpp:22158
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:23609
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
定义 json.hpp:23972
BooleanType boolean_t
a type for a boolean
定义 json.hpp:19675
detail::value_t value_t
定义 json.hpp:19490
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
定义 json.hpp:19654
reference operator+=(const typename object_t::value_type &val)
add an object to an object
定义 json.hpp:22502
const_iterator cbegin() const noexcept
returns a const iterator to the first element
定义 json.hpp:22110
reference operator[](typename object_t::key_type key)
access specified object element
定义 json.hpp:21445
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
定义 json.hpp:20882
~basic_json() noexcept
destructor
定义 json.hpp:20580
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
定义 json.hpp:22179
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
定义 json.hpp:20228
void swap(typename binary_t::container_type &other)
exchanges the values
定义 json.hpp:22881
binary_t & get_binary()
get a binary value
定义 json.hpp:21230
const_iterator begin() const noexcept
returns an iterator to the first element
定义 json.hpp:22103
constexpr bool is_number() const noexcept
return whether value is a number
定义 json.hpp:20655
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
定义 json.hpp:22709
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
定义 json.hpp:23746
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
定义 json.hpp:21111
const_reference operator[](T *key) const
定义 json.hpp:21489
data(const value_t v)
定义 json.hpp:23523
reference operator[](size_type idx)
access specified array element
定义 json.hpp:21386
basic_json(const JsonRef &ref)
定义 json.hpp:20467
JSONSerializer< T, SFINAE > json_serializer
定义 json.hpp:19494
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
定义 json.hpp:20557
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:23628
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
定义 json.hpp:21148
NumberIntegerType number_integer_t
a type for a number (integer)
定义 json.hpp:19679
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
定义 json.hpp:20871
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
定义 json.hpp:21348
constexpr bool is_binary() const noexcept
return whether value is a binary array
定义 json.hpp:20704
void swap(object_t &other)
exchanges the values
定义 json.hpp:22833
basic_json unflatten() const
unflatten a previously flattened JSON value
定义 json.hpp:24009
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
定义 json.hpp:22689
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
定义 json.hpp:20320
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
定义 json.hpp:22209
bool empty() const noexcept
checks whether the container is empty.
定义 json.hpp:22232
void swap(array_t &other)
exchanges the values
定义 json.hpp:22817
void erase(const size_type idx)
remove element from a JSON array given an index
定义 json.hpp:21948
reference operator+=(basic_json &&val)
add an object to an array
定义 json.hpp:22439
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
定义 json.hpp:22071
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
定义 json.hpp:20620
reference emplace_back(Args &&... args)
add an object to an array
定义 json.hpp:22535
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:21653
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
定义 json.hpp:20331
data() noexcept=default
StringType string_t
a type for a string
定义 json.hpp:19671
friend class ::nlohmann::detail::parser
定义 json.hpp:19435
void push_back(const basic_json &val)
add an object to an array
定义 json.hpp:22447
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
定义 json.hpp:21603
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
定义 json.hpp:21310
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
定义 json.hpp:23869
json_value m_value
the value of the current element
定义 json.hpp:23521
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
定义 json.hpp:22172
constexpr bool is_boolean() const noexcept
return whether value is a boolean
定义 json.hpp:20648
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
定义 json.hpp:22037
reference front()
access the first element
定义 json.hpp:21720
constexpr bool is_primitive() const noexcept
return whether type is primitive
定义 json.hpp:20627
constexpr bool is_null() const noexcept
return whether value is null
定义 json.hpp:20641
void clear() noexcept
clears the contents
定义 json.hpp:22353
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:23620
basic_json(basic_json &&other) noexcept
move constructor
定义 json.hpp:20540
iter_impl< basic_json > iterator
an iterator for a basic_json container
定义 json.hpp:19554
basic_json(const value_t v)
create an empty value with a given type
定义 json.hpp:20141
const_reference operator[](size_type idx) const
access specified array element
定义 json.hpp:21432
std::ptrdiff_t difference_type
a type to represent differences between iterators
定义 json.hpp:19541
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
定义 json.hpp:22631
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
定义 json.hpp:22165
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
定义 json.hpp:19683
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
定义 json.hpp:23469
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
定义 json.hpp:23586
void swap(string_t &other)
exchanges the values
定义 json.hpp:22849
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
定义 json.hpp:20175
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
定义 json.hpp:19558
const_reference at(size_type idx) const
access specified array element with bounds checking
定义 json.hpp:21287
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
定义 json.hpp:19695
basic_json(const basic_json &other)
copy constructor
定义 json.hpp:20471
void push_back(const typename object_t::value_type &val)
add an object to an object
定义 json.hpp:22479
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
定义 json.hpp:22560
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
定义 json.hpp:23579
constexpr bool is_object() const noexcept
return whether value is an object
定义 json.hpp:20683
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
定义 json.hpp:23595
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
定义 json.hpp:23761
iterator insert_iterator(const_iterator pos, Args &&... args)
定义 json.hpp:22592
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
定义 json.hpp:20358
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
定义 json.hpp:22055
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
定义 json.hpp:23672
const_iterator find(KeyType &&key) const
find an element in a JSON object
定义 json.hpp:22023
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer
定义 json.hpp:19492
an internal type for a backed binary type
定义 json.hpp:5915
bool operator!=(const byte_container_with_subtype &rhs) const
定义 json.hpp:5955
byte_container_with_subtype() noexcept(noexcept(container_type()))
定义 json.hpp:5921
std::uint64_t subtype_type
定义 json.hpp:5918
bool operator==(const byte_container_with_subtype &rhs) const
定义 json.hpp:5949
BinaryType container_type
定义 json.hpp:5917
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
定义 json.hpp:5943
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
定义 json.hpp:5931
constexpr subtype_type subtype() const noexcept
return the binary subtype
定义 json.hpp:5970
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
定义 json.hpp:5936
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
定义 json.hpp:5977
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
定义 json.hpp:5926
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
定义 json.hpp:5962
void clear_subtype() noexcept
clears the binary subtype
定义 json.hpp:5984
deserialization of CBOR, MessagePack, and UBJSON values
定义 json.hpp:9236
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
定义 json.hpp:9252
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
定义 json.hpp:9273
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
定义 json.hpp:15103
void write_bson(const BasicJsonType &j)
定义 json.hpp:15123
static constexpr CharType to_char_type(std::uint8_t x) noexcept
定义 json.hpp:16858
static CharType to_char_type(std::uint8_t x) noexcept
定义 json.hpp:16865
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
定义 json.hpp:15114
static constexpr CharType to_char_type(InputCharType x) noexcept
定义 json.hpp:16887
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
定义 json.hpp:15802
void write_msgpack(const BasicJsonType &j)
定义 json.hpp:15476
void write_cbor(const BasicJsonType &j)
定义 json.hpp:15152
general exception of the basic_json class
定义 json.hpp:4396
const int id
the id of the exception
定义 json.hpp:4405
static std::string diagnostics(std::nullptr_t)
定义 json.hpp:4416
static std::string name(const std::string &ename, int id_)
定义 json.hpp:4411
const char * what() const noexcept override
returns the explanatory string
定义 json.hpp:4399
static std::string diagnostics(const BasicJsonType *leaf_element)
定义 json.hpp:4422
定义 json.hpp:6212
char char_type
定义 json.hpp:6214
file_input_adapter(const file_input_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept
定义 json.hpp:6230
file_input_adapter(file_input_adapter &&) noexcept=default
定义 json.hpp:6250
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
定义 json.hpp:6273
~input_stream_adapter()
定义 json.hpp:6254
std::char_traits< char >::int_type get_character()
定义 json.hpp:6283
char char_type
定义 json.hpp:6252
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
定义 json.hpp:6264
exception indicating errors with iterators
定义 json.hpp:4547
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
定义 json.hpp:4550
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
定义 json.hpp:12940
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
定义 json.hpp:13514
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
定义 json.hpp:13077
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
定义 json.hpp:13459
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
定义 json.hpp:13067
bool operator<(const iter_impl &other) const
comparison: smaller
定义 json.hpp:13406
bool operator<=(const iter_impl &other) const
comparison: less than or equal
定义 json.hpp:13441
iter_impl & operator-=(difference_type i)
subtract from iterator
定义 json.hpp:13505
iter_impl & operator--()
pre-decrement (–it)
定义 json.hpp:13320
const object_t::key_type & key() const
return the key of an object iterator
定义 json.hpp:13614
bool operator==(const IterImpl &other) const
comparison: equal
定义 json.hpp:13361
iter_impl operator++(int) &
post-increment (it++)
定义 json.hpp:13258
iter_impl & operator+=(difference_type i)
add to iterator
定义 json.hpp:13468
reference operator[](difference_type n) const
access to successor
定义 json.hpp:13576
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
定义 json.hpp:12972
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
定义 json.hpp:12970
pointer operator->() const
dereference the iterator
定义 json.hpp:13216
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
定义 json.hpp:13639
difference_type operator-(const iter_impl &other) const
return difference
定义 json.hpp:13547
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
定义 json.hpp:12965
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
定义 json.hpp:13525
reference value() const
return the value of an iterator
定义 json.hpp:13630
bool operator>(const iter_impl &other) const
comparison: greater than
定义 json.hpp:13450
iter_impl & operator++()
pre-increment (++it)
定义 json.hpp:13269
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
定义 json.hpp:12968
reference operator*() const
return a reference to the value pointed to by the iterator
定义 json.hpp:13172
iter_impl operator-(difference_type i) const
subtract from iterator
定义 json.hpp:13536
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
定义 json.hpp:12976
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
定义 json.hpp:13052
bool operator!=(const IterImpl &other) const
comparison: not equal
定义 json.hpp:13397
iter_impl operator--(int) &
post-decrement (it–)
定义 json.hpp:13309
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
定义 json.hpp:13042
void set_end() noexcept
set the iterator past the last value
定义 json.hpp:13133
定义 json.hpp:12920
iteration_proxy_value operator++(int) &
定义 json.hpp:5266
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
定义 json.hpp:5275
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
定义 json.hpp:5281
std::ptrdiff_t difference_type
定义 json.hpp:5212
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
定义 json.hpp:5233
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
定义 json.hpp:5258
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
定义 json.hpp:5323
const string_type & key() const
return key of the iterator
定义 json.hpp:5287
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
std::input_iterator_tag iterator_category
定义 json.hpp:5216
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
定义 json.hpp:5217
proxy class for the items() function
定义 json.hpp:12919
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
定义 json.hpp:5356
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
定义 json.hpp:5340
iteration_proxy & operator=(iteration_proxy const &)=default
定义 json.hpp:6305
char_traits< char_type >::int_type get_character()
定义 json.hpp:6313
iterator_input_adapter(IteratorType first, IteratorType last)
定义 json.hpp:6309
typename std::iterator_traits< IteratorType >::value_type char_type
定义 json.hpp:6307
定义 json.hpp:14844
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
定义 json.hpp:14852
json_ref(value_type &&value)
定义 json.hpp:14848
value_type const & operator*() const
定义 json.hpp:14883
value_type const * operator->() const
定义 json.hpp:14888
json_ref(std::initializer_list< json_ref > init)
定义 json.hpp:14856
json_ref(Args &&... args)
定义 json.hpp:14863
value_type moved_or_copied() const
定义 json.hpp:14874
BasicJsonType value_type
定义 json.hpp:14846
a template for a reverse iterator class
定义 json.hpp:13693
json_reverse_iterator operator++(int) &
post-increment (it++)
定义 json.hpp:13709
json_reverse_iterator operator--(int) &
post-decrement (it–)
定义 json.hpp:13721
json_reverse_iterator & operator++()
pre-increment (++it)
定义 json.hpp:13715
std::ptrdiff_t difference_type
定义 json.hpp:13695
json_reverse_iterator & operator+=(difference_type i)
add to iterator
定义 json.hpp:13733
reference operator[](difference_type n) const
access to successor
定义 json.hpp:13757
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
定义 json.hpp:13763
difference_type operator-(const json_reverse_iterator &other) const
return difference
定义 json.hpp:13751
typename Base::reference reference
the reference type for the pointed-to element
定义 json.hpp:13699
reference value() const
return the value of an iterator
定义 json.hpp:13770
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
定义 json.hpp:13706
json_reverse_iterator & operator--()
pre-decrement (–it)
定义 json.hpp:13727
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
定义 json.hpp:13697
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
定义 json.hpp:13745
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
定义 json.hpp:13702
json_reverse_iterator operator+(difference_type i) const
add to iterator
定义 json.hpp:13739
定义 json.hpp:7314
typename BasicJsonType::number_unsigned_t number_unsigned_t
定义 json.hpp:7317
bool end_object()
定义 json.hpp:7367
bool start_object(std::size_t=static_cast< std::size_t >(-1))
定义 json.hpp:7357
bool binary(binary_t &)
定义 json.hpp:7352
bool number_integer(number_integer_t)
定义 json.hpp:7332
bool start_array(std::size_t=static_cast< std::size_t >(-1))
定义 json.hpp:7372
bool boolean(bool)
定义 json.hpp:7327
bool null()
定义 json.hpp:7322
bool end_array()
定义 json.hpp:7377
bool number_unsigned(number_unsigned_t)
定义 json.hpp:7337
bool string(string_t &)
定义 json.hpp:7347
typename BasicJsonType::binary_t binary_t
定义 json.hpp:7320
bool number_float(number_float_t, const string_t &)
定义 json.hpp:7342
bool parse_error(std::size_t, const std::string &, const detail::exception &)
定义 json.hpp:7382
bool key(string_t &)
定义 json.hpp:7362
typename BasicJsonType::number_integer_t number_integer_t
定义 json.hpp:7316
typename BasicJsonType::number_float_t number_float_t
定义 json.hpp:7318
typename BasicJsonType::string_t string_t
定义 json.hpp:7319
bool boolean(bool val)
定义 json.hpp:7038
bool parse_error(std::size_t, const std::string &, const Exception &ex)
定义 json.hpp:7195
typename BasicJsonType::string_t string_t
定义 json.hpp:7012
bool number_float(number_float_t val, const string_t &)
定义 json.hpp:7056
constexpr bool is_errored() const
定义 json.hpp:7207
bool string(string_t &val)
定义 json.hpp:7062
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
定义 json.hpp:7010
typename BasicJsonType::binary_t binary_t
定义 json.hpp:7013
bool start_object(std::size_t len)
定义 json.hpp:7074
bool start_array(std::size_t len)
定义 json.hpp:7145
typename BasicJsonType::number_integer_t number_integer_t
定义 json.hpp:7009
bool end_array()
定义 json.hpp:7162
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
bool key(string_t &val)
定义 json.hpp:7092
bool end_object()
定义 json.hpp:7109
typename BasicJsonType::parse_event_t parse_event_t
定义 json.hpp:7015
typename BasicJsonType::parser_callback_t parser_callback_t
定义 json.hpp:7014
bool null()
定义 json.hpp:7032
bool number_unsigned(number_unsigned_t val)
定义 json.hpp:7050
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
定义 json.hpp:7017
typename BasicJsonType::number_float_t number_float_t
定义 json.hpp:7011
bool number_integer(number_integer_t val)
定义 json.hpp:7044
bool binary(binary_t &val)
定义 json.hpp:7068
SAX implementation to create a JSON value from SAX events
定义 json.hpp:6824
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool string(string_t &val)
定义 json.hpp:6878
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
定义 json.hpp:6837
bool parse_error(std::size_t, const std::string &, const Exception &ex)
定义 json.hpp:6945
bool null()
定义 json.hpp:6848
typename BasicJsonType::string_t string_t
定义 json.hpp:6829
bool start_object(std::size_t len)
定义 json.hpp:6890
typename BasicJsonType::number_unsigned_t number_unsigned_t
定义 json.hpp:6827
bool number_unsigned(number_unsigned_t val)
定义 json.hpp:6866
bool number_integer(number_integer_t val)
定义 json.hpp:6860
typename BasicJsonType::number_integer_t number_integer_t
定义 json.hpp:6826
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
定义 json.hpp:6884
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool boolean(bool val)
定义 json.hpp:6854
bool end_array()
定义 json.hpp:6934
bool number_float(number_float_t val, const string_t &)
定义 json.hpp:6872
bool end_object()
定义 json.hpp:6912
constexpr bool is_errored() const
定义 json.hpp:6957
typename BasicJsonType::binary_t binary_t
定义 json.hpp:6830
typename BasicJsonType::number_float_t number_float_t
定义 json.hpp:6828
bool start_array(std::size_t len)
定义 json.hpp:6922
bool key(string_t &val)
定义 json.hpp:6902
定义 json.hpp:7431
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
定义 json.hpp:7458
token_type
token types for the parser
定义 json.hpp:7435
lexical analysis
定义 json.hpp:7508
bool skip_bom()
skip the UTF-8 byte order mark
定义 json.hpp:8882
void skip_whitespace()
定义 json.hpp:8896
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
定义 json.hpp:7519
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
定义 json.hpp:8869
std::string get_token_string() const
定义 json.hpp:8844
constexpr number_integer_t get_number_integer() const noexcept
return integer value
定义 json.hpp:8808
constexpr position_t get_position() const noexcept
return position of last read token
定义 json.hpp:8836
token_type scan()
定义 json.hpp:8905
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
定义 json.hpp:8814
typename lexer_base< BasicJsonType >::token_type token_type
定义 json.hpp:7517
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
定义 json.hpp:8826
constexpr number_float_t get_number_float() const noexcept
return floating-point value
定义 json.hpp:8820
exception indicating other library errors
定义 json.hpp:4599
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
定义 json.hpp:4602
exception indicating access out of the defined range
定义 json.hpp:4582
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
定义 json.hpp:4585
定义 json.hpp:15061
output_adapter(StringType &s)
定义 json.hpp:15072
output_adapter(std::basic_ostream< CharType > &s)
定义 json.hpp:15068
output_adapter(std::vector< CharType, AllocatorType > &vec)
定义 json.hpp:15064
output adapter for output streams
定义 json.hpp:15013
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
定义 json.hpp:15015
void write_character(CharType c) override
定义 json.hpp:15019
output adapter for basic_string
定义 json.hpp:15038
void write_character(CharType c) override
定义 json.hpp:15044
output_string_adapter(StringType &s) noexcept
定义 json.hpp:15040
output adapter for byte vectors
定义 json.hpp:14988
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
定义 json.hpp:14990
void write_character(CharType c) override
定义 json.hpp:14994
exception indicating a parse error
定义 json.hpp:4494
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
定义 json.hpp:4506
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
定义 json.hpp:4514
const std::size_t byte
byte index of the parse error
定义 json.hpp:4531
syntax analysis
定义 json.hpp:12253
parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
定义 json.hpp:12263
void parse(const bool strict, BasicJsonType &result)
public parser interface
定义 json.hpp:12285
bool accept(const bool strict=true)
public accept interface
定义 json.hpp:12345
bool sax_parse(SAX *sax, const bool strict=true)
定义 json.hpp:12353
定义 json.hpp:12757
primitive_iterator_t & operator++() noexcept
定义 json.hpp:12819
primitive_iterator_t & operator-=(difference_type n) noexcept
定义 json.hpp:12851
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
定义 json.hpp:12786
primitive_iterator_t & operator--() noexcept
定义 json.hpp:12832
void set_end() noexcept
set iterator to a defined past the end
定义 json.hpp:12780
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
定义 json.hpp:12802
constexpr bool is_end() const noexcept
return whether the iterator is at end
定义 json.hpp:12792
primitive_iterator_t operator++(int) &noexcept
定义 json.hpp:12825
primitive_iterator_t & operator+=(difference_type n) noexcept
定义 json.hpp:12845
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
定义 json.hpp:12797
constexpr difference_type get_value() const noexcept
定义 json.hpp:12768
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
定义 json.hpp:12814
primitive_iterator_t operator+(difference_type n) noexcept
定义 json.hpp:12807
void set_begin() noexcept
set iterator to a defined beginning
定义 json.hpp:12774
primitive_iterator_t operator--(int) &noexcept
定义 json.hpp:12838
定义 json.hpp:18084
std::array< char, 512 > string_buffer
string buffer
定义 json.hpp:19008
std::uint8_t state
定义 json.hpp:18426
std::size_t bytes_after_last_accept
定义 json.hpp:18430
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
定义 json.hpp:18099
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
定义 json.hpp:18424
std::size_t undumped_chars
定义 json.hpp:18431
const char thousands_sep
the locale's thousand separator character
定义 json.hpp:19003
const char decimal_point
the locale's decimal point character
定义 json.hpp:19005
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
定义 json.hpp:19016
string_t indent_string
the indentation string
定义 json.hpp:19013
const std::lconv * loc
the locale
定义 json.hpp:19001
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
定义 json.hpp:18998
const char indent_char
the indentation character
定义 json.hpp:19011
std::size_t bytes
定义 json.hpp:18427
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
定义 json.hpp:18139
serializer(const serializer &)=delete
serializer(serializer &&)=delete
定义 json.hpp:6629
span_input_adapter(CharT b, std::size_t l)
定义 json.hpp:6637
span_input_adapter(IteratorType first, IteratorType last)
定义 json.hpp:6644
contiguous_bytes_input_adapter && get()
定义 json.hpp:6647
exception indicating executing a member function with a wrong type
定义 json.hpp:4565
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
定义 json.hpp:4568
std::char_traits< char >::int_type get_character() noexcept
定义 json.hpp:6471
wide_string_input_adapter(BaseInputAdapter base)
定义 json.hpp:6468
char char_type
定义 json.hpp:6466
JSON Pointer defines a string syntax for identifying a specific value within a JSON document
定义 json.hpp:13865
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
定义 json.hpp:13960
typename string_t_helper< RefStringType >::type string_t
定义 json.hpp:13887
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
定义 json.hpp:13967
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
定义 json.hpp:14760
json_pointer(const string_t &s="")
create JSON pointer
定义 json.hpp:13891
bool empty() const noexcept
return whether pointer points to the root document
定义 json.hpp:14026
void pop_back()
remove last reference token
定义 json.hpp:13988
string_t to_string() const
return a string representation of the JSON pointer
定义 json.hpp:13897
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
定义 json.hpp:13945
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
定义 json.hpp:14019
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
定义 json.hpp:14810
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
定义 json.hpp:13927
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
定义 json.hpp:13952
json_pointer parent_pointer() const
returns the parent of this JSON pointer
定义 json.hpp:13974
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
定义 json.hpp:13937
friend class json_pointer
定义 json.hpp:13871
const string_t & back() const
return last reference token
定义 json.hpp:14000
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
定义 json.hpp:14785
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
定义 json.hpp:13918
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
定义 json.hpp:14012
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
定义 json.hpp:5402
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
定义 json.hpp:2620
#define JSON_HEDLEY_CONST
定义 json.hpp:1842
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
定义 json.hpp:1126
#define JSON_INLINE_VARIABLE
定义 json.hpp:2523
#define JSON_HEDLEY_WARN_UNUSED_RESULT
定义 json.hpp:1472
#define JSON_PRIVATE_UNLESS_TESTED
定义 json.hpp:2583
#define NLOHMANN_JSON_VERSION_PATCH
定义 json.hpp:94
#define JSON_HEDLEY_LIKELY(expr)
定义 json.hpp:1737
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
定义 json.hpp:14760
#define JSON_HEDLEY_NON_NULL(...)
定义 json.hpp:1630
#define JSON_INTERNAL_CATCH(exception)
定义 json.hpp:2550
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
定义 json.hpp:24480
#define JSON_HEDLEY_RETURNS_NON_NULL
定义 json.hpp:2071
#define JSON_CATCH(exception)
定义 json.hpp:2549
#define JSON_ASSERT(x)
定义 json.hpp:2576
#define JSON_THROW(exception)
定义 json.hpp:2547
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
定义 json.hpp:101
#define NLOHMANN_JSON_VERSION_MAJOR
定义 json.hpp:92
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
定义 json.hpp:14810
#define NLOHMANN_BASIC_JSON_TPL
定义 json.hpp:2630
#define JSON_HEDLEY_UNLIKELY(expr)
定义 json.hpp:1738
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
定义 json.hpp:12143
#define JSON_TRY
定义 json.hpp:2548
#define NLOHMANN_JSON_NAMESPACE_END
定义 json.hpp:168
#define JSON_NO_UNIQUE_ADDRESS
定义 json.hpp:2529
#define NLOHMANN_JSON_VERSION_MINOR
定义 json.hpp:93
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
定义 json.hpp:2810
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
定义 json.hpp:14785
#define NLOHMANN_JSON_NAMESPACE_BEGIN
定义 json.hpp:158
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
定义 json.hpp:12140
#define JSON_HEDLEY_DIAGNOSTIC_POP
定义 json.hpp:1127
#define JSON_EXPLICIT
定义 json.hpp:2847
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
定义 json.hpp:1420
#define JSON_HEDLEY_PURE
定义 json.hpp:1811
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
定义 json.hpp:22906
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
定义 json.hpp:17423
cached_power get_cached_power_for_binary_exponent(int e)
定义 json.hpp:17259
Target reinterpret_bits(const Source source)
定义 json.hpp:16979
boundaries compute_boundaries(FloatType value)
定义 json.hpp:17120
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
定义 json.hpp:17477
constexpr int kAlpha
定义 json.hpp:17242
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
定义 json.hpp:17759
constexpr int kGamma
定义 json.hpp:17243
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
定义 json.hpp:17518
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
定义 json.hpp:17859
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
定义 json.hpp:17911
constexpr bool is_transparent()
定义 json.hpp:4218
constexpr bool is_c_string()
定义 json.hpp:4190
detail namespace with internal helper functions
定义 json.hpp:273
make_integer_sequence< size_t, N > make_index_sequence
定义 json.hpp:3215
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
定义 json.hpp:4293
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
定义 json.hpp:4100
input_format_t
the supported input formats
定义 json.hpp:6200
typename detector< nonesuch, void, Op, Args... >::type detected_t
定义 json.hpp:324
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
定义 json.hpp:5804
decltype(T::to_json(std::declval< Args >()...)) to_json_function
定义 json.hpp:3541
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
定义 json.hpp:9082
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
定义 json.hpp:4314
decltype(std::declval< T & >().end_object()) end_object_function_t
定义 json.hpp:9094
OutStringType concat(Args &&... args)
定义 json.hpp:4373
typename T::value_type value_type_t
定义 json.hpp:3526
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
定义 json.hpp:3246
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
定义 json.hpp:17996
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
定义 json.hpp:9062
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
定义 json.hpp:333
is_detected< string_can_append, StringType, Arg > detect_string_can_append
定义 json.hpp:4296
typename std::enable_if< B, T >::type enable_if_t
定义 json.hpp:3119
parse_event_t
定义 json.hpp:12227
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
定义 json.hpp:4096
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
定义 json.hpp:318
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
定义 json.hpp:4016
typename T::pointer pointer_t
定义 json.hpp:3532
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
定义 json.hpp:5034
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
定义 json.hpp:4845
typename utility_internal::Gen< T, N >::type make_integer_sequence
定义 json.hpp:3207
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
定义 json.hpp:14983
typename detected_or< Default, Op, Args... >::type detected_or_t
定义 json.hpp:330
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
定义 json.hpp:9090
decltype(std::declval< T & >().null()) null_function_t
定义 json.hpp:9059
T conditional_static_cast(U value)
定义 json.hpp:4074
typename T::difference_type difference_type_t
定义 json.hpp:3529
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
定义 json.hpp:9086
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
定义 json.hpp:9074
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
定义 json.hpp:2995
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
定义 json.hpp:9097
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
定义 json.hpp:4308
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
定义 json.hpp:5366
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
定义 json.hpp:4047
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
定义 json.hpp:3620
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
定义 json.hpp:4043
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
定义 json.hpp:6602
cbor_tag_handler_t
how to treat CBOR tags
定义 json.hpp:9209
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
定义 json.hpp:3771
make_index_sequence< sizeof...(Ts)> index_sequence_for
定义 json.hpp:3223
void concat_into(OutStringType &)
定义 json.hpp:4289
constexpr bool value_in_range_of(T val)
定义 json.hpp:4174
value_t
the JSON type enumeration
定义 json.hpp:2897
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
decltype(T::from_json(std::declval< Args >()...)) from_json_function
定义 json.hpp:3544
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
定义 json.hpp:4928
std::size_t hash(const BasicJsonType &j)
hash a JSON value
定义 json.hpp:6046
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
定义 json.hpp:9066
typename make_void< Ts... >::type void_t
定义 json.hpp:279
std::size_t combine(std::size_t seed, std::size_t h) noexcept
定义 json.hpp:6028
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
定义 json.hpp:9104
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
定义 json.hpp:2926
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
定义 json.hpp:6545
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
定义 json.hpp:3768
typename T::iterator_category iterator_category_t
定义 json.hpp:3538
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
定义 json.hpp:13815
error_handler_t
how to treat decoding errors
定义 json.hpp:18076
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
定义 json.hpp:4034
std::size_t concat_length()
定义 json.hpp:4258
std::integral_constant< bool, Value > bool_constant
定义 json.hpp:4180
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
定义 json.hpp:3105
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
定义 json.hpp:4688
typename T::key_compare detect_key_compare
定义 json.hpp:3604
void to_json(BasicJsonType &j, T b) noexcept
定义 json.hpp:5666
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
定义 json.hpp:4702
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
定义 json.hpp:336
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
定义 json.hpp:4305
decltype(std::declval< T & >().end_array()) end_array_function_t
定义 json.hpp:9101
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
定义 json.hpp:5028
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
定义 json.hpp:4311
typename T::key_type key_type_t
定义 json.hpp:3523
typename T::reference reference_t
定义 json.hpp:3535
typename T::is_transparent detect_is_transparent
定义 json.hpp:4010
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
定义 json.hpp:4302
typename T::mapped_type mapped_type_t
定义 json.hpp:3520
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
定义 json.hpp:4299
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
定义 json.hpp:3014
void int_to_string(string_type &target, std::size_t value)
定义 json.hpp:5203
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
定义 json.hpp:9078
decltype(std::declval< T >().template get< U >()) get_template_function
定义 json.hpp:3547
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
定义 json.hpp:9070
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
定义 json.hpp:12243
定义 json.hpp:24486
定义 json.hpp:5387
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
定义 json.hpp:24561
namespace for Niels Lohmann
定义 json.hpp:5857
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
定义 json.hpp:5881
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
定义 json.hpp:5871
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
定义 json.hpp:5861
typename BasicJsonType::object_t object_t
定义 json.hpp:3613
typename BasicJsonType::default_object_comparator_t object_comparator_t
定义 json.hpp:3614
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
定义 json.hpp:3615
signed char char_type
定义 json.hpp:3659
static constexpr int_type eof() noexcept
定义 json.hpp:3673
uint64_t int_type
定义 json.hpp:3660
static char_type to_char_type(int_type i) noexcept
定义 json.hpp:3668
static int_type to_int_type(char_type c) noexcept
定义 json.hpp:3663
static char_type to_char_type(int_type i) noexcept
定义 json.hpp:3644
static constexpr int_type eof() noexcept
定义 json.hpp:3649
unsigned char char_type
定义 json.hpp:3635
uint64_t int_type
定义 json.hpp:3636
static int_type to_int_type(char_type c) noexcept
定义 json.hpp:3639
定义 json.hpp:3629
定义 json.hpp:3684
定义 json.hpp:305
std::false_type value_t
定义 json.hpp:306
Default type
定义 json.hpp:307
定义 json.hpp:17107
diyfp w
定义 json.hpp:17108
diyfp minus
定义 json.hpp:17109
diyfp plus
定义 json.hpp:17110
定义 json.hpp:17246
std::uint64_t f
定义 json.hpp:17247
int e
定义 json.hpp:17248
int k
定义 json.hpp:17249
定义 json.hpp:16989
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
定义 json.hpp:17013
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
定义 json.hpp:17095
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
定义 json.hpp:17078
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
定义 json.hpp:17001
constexpr diyfp(std::uint64_t f_, int e_) noexcept
定义 json.hpp:16995
static constexpr int kPrecision
定义 json.hpp:16990
std::uint64_t f
定义 json.hpp:16992
int e
定义 json.hpp:16993
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
定义 json.hpp:5591
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
定义 json.hpp:5566
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
定义 json.hpp:5556
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
定义 json.hpp:5578
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
定义 json.hpp:5607
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
定义 json.hpp:5495
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
定义 json.hpp:5504
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
定义 json.hpp:5449
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
定义 json.hpp:5517
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
定义 json.hpp:5543
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
定义 json.hpp:5530
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
定义 json.hpp:5626
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
定义 json.hpp:5647
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
定义 json.hpp:5636
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
定义 json.hpp:5471
static void construct(BasicJsonType &j, const CompatibleStringType &str)
定义 json.hpp:5482
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
定义 json.hpp:5462
定义 json.hpp:5443
定义 json.hpp:5123
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
定义 json.hpp:5125
typename BasicJsonType::template json_serializer< T, void > serializer
定义 json.hpp:3566
定义 json.hpp:3551
定义 json.hpp:3607
typename BasicJsonType::template json_serializer< T, void > serializer
定义 json.hpp:3581
typename BasicJsonType::template json_serializer< T, void > serializer
定义 json.hpp:3596
定义 json.hpp:3591
定义 json.hpp:4639
定义 json.hpp:3147
T value_type
定义 json.hpp:3148
static constexpr std::size_t size() noexcept
定义 json.hpp:3149
an iterator value
定义 json.hpp:12873
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
定义 json.hpp:12877
primitive_iterator_t primitive_iterator
generic iterator for all other types
定义 json.hpp:12879
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
定义 json.hpp:12875
定义 json.hpp:3500
定义 json.hpp:3487
定义 json.hpp:4205
定义 json.hpp:4001
static constexpr auto value
定义 json.hpp:3843
定义 json.hpp:3971
定义 json.hpp:3778
ConstructibleStringType laundered_type
定义 json.hpp:3854
static constexpr auto value
定义 json.hpp:3857
定义 json.hpp:3974
定义 json.hpp:3716
定义 json.hpp:321
定义 json.hpp:3559
static constexpr bool value
定义 json.hpp:3560
typename std::iterator_traits< T >::value_type value_type
定义 json.hpp:6522
定义 json.hpp:3731
定义 json.hpp:3980
定义 json.hpp:3510
定义 json.hpp:4062
char x[2]
定义 json.hpp:4063
定义 json.hpp:4058
static one test(decltype(&C::capacity))
char one
定义 json.hpp:4059
static two test(...)
@ value
定义 json.hpp:4069
定义 json.hpp:3750
static constexpr bool value
定义 json.hpp:3764
定义 json.hpp:9141
定义 json.hpp:9110
static constexpr bool value
定义 json.hpp:9123
定义 json.hpp:3991
定义 json.hpp:4227
typename std::iterator_traits< iterator_type >::value_type char_type
定义 json.hpp:6533
static adapter_type create(IteratorType first, IteratorType last)
定义 json.hpp:6537
iterator_input_adapter< iterator_type > adapter_type
定义 json.hpp:6511
typename std::iterator_traits< iterator_type >::value_type char_type
定义 json.hpp:6510
static adapter_type create(IteratorType first, IteratorType last)
定义 json.hpp:6513
IteratorType iterator_type
定义 json.hpp:6509
std::random_access_iterator_tag iterator_category
定义 json.hpp:3327
定义 json.hpp:3315
定义 json.hpp:3296
Default base class of the basic_json class.
定义 json.hpp:13812
定义 json.hpp:276
void type
定义 json.hpp:277
定义 json.hpp:3691
定义 json.hpp:291
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
定义 json.hpp:14969
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
定义 json.hpp:3060
std::size_t chars_read_current_line
the number of characters read in the current line
定义 json.hpp:3064
std::size_t lines_read
the number of lines read
定义 json.hpp:3066
std::size_t chars_read_total
the total number of characters read
定义 json.hpp:3062
定义 json.hpp:3230
定义 json.hpp:3236
static JSON_INLINE_VARIABLE constexpr T value
定义 json.hpp:3237
定义 json.hpp:5824
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
定义 json.hpp:5826
定义 json.hpp:3186
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
定义 json.hpp:3187
static constexpr bool test(T val)
定义 json.hpp:4158
static constexpr bool test(T)
定义 json.hpp:4167
static constexpr bool test(T val)
定义 json.hpp:4112
static constexpr bool test(T val)
定义 json.hpp:4132
static constexpr bool test(T val)
定义 json.hpp:4122
static constexpr bool test(T val)
定义 json.hpp:4142
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
定义 json.hpp:6403
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
定义 json.hpp:6345
SAX interface
定义 json.hpp:6694
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
定义 json.hpp:6695
typename BasicJsonType::string_t string_t
定义 json.hpp:6698
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
定义 json.hpp:6697
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
定义 json.hpp:6696
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
定义 json.hpp:6699
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
定义 json.hpp:19058
std::vector< std::pair< const Key, T >, Allocator > Container
定义 json.hpp:19061
std::pair< iterator, bool > insert(value_type &&value)
定义 json.hpp:19352
typename Container::value_type value_type
定义 json.hpp:19065
std::equal_to< Key > key_compare
定义 json.hpp:19069
iterator erase(iterator pos)
定义 json.hpp:19230
T mapped_type
定义 json.hpp:19060
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
定义 json.hpp:19075
T & operator[](KeyType &&key)
定义 json.hpp:19117
typename Container::iterator iterator
定义 json.hpp:19062
const T & at(KeyType &&key) const
定义 json.hpp:19177
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
定义 json.hpp:19371
T & at(KeyType &&key)
定义 json.hpp:19149
const T & operator[](KeyType &&key) const
定义 json.hpp:19129
iterator find(const key_type &key)
定义 json.hpp:19314
iterator erase(iterator first, iterator last)
定义 json.hpp:19235
const T & at(const key_type &key) const
定义 json.hpp:19162
const_iterator find(const key_type &key) const
定义 json.hpp:19340
T & operator[](const key_type &key)
定义 json.hpp:19110
size_type erase(KeyType &&key)
定义 json.hpp:19211
typename Container::size_type size_type
定义 json.hpp:19064
ordered_map() noexcept(noexcept(Container()))
定义 json.hpp:19074
void insert(InputIt first, InputIt last)
定义 json.hpp:19375
size_type count(const key_type &key) const
定义 json.hpp:19288
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
定义 json.hpp:19097
size_type erase(const key_type &key)
定义 json.hpp:19190
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
定义 json.hpp:19079
std::pair< iterator, bool > insert(const value_type &value)
定义 json.hpp:19357
size_type count(KeyType &&key) const
定义 json.hpp:19302
Key key_type
定义 json.hpp:19059
ordered_map(It first, It last, const Allocator &alloc=Allocator())
定义 json.hpp:19077
const T & operator[](const key_type &key) const
定义 json.hpp:19122
iterator find(KeyType &&key)
定义 json.hpp:19328
T & at(const key_type &key)
定义 json.hpp:19134
typename Container::const_iterator const_iterator
定义 json.hpp:19063
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
定义 json.hpp:19082
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
定义 json.hpp:24530
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
定义 json.hpp:24544